diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-12-03 18:42:09 +0100 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-12-03 18:51:45 +0100 |
commit | cae9b3a92fe86d9a1e9a243570229d9e40ebd341 (patch) | |
tree | f21054aa32feaa6b8ab07f26d723657609b51788 | |
parent | 1c6c5ac69aed0f7dd35f5007105ed9ac6f1f568d (diff) | |
download | sonarqube-cae9b3a92fe86d9a1e9a243570229d9e40ebd341.tar.gz sonarqube-cae9b3a92fe86d9a1e9a243570229d9e40ebd341.zip |
SONAR-5804 fix source lines purge of multi module projects
13 files changed, 181 insertions, 220 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java index bcb7b7f4454..1bb8802150e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java @@ -23,15 +23,13 @@ package org.sonar.server.computation; import org.sonar.api.config.Settings; import org.sonar.core.component.ComponentDto; import org.sonar.core.computation.db.AnalysisReportDto; -import org.sonar.server.computation.dbcleaner.ProjectPurgeTask; import org.sonar.core.persistence.DbSession; import org.sonar.core.purge.PurgeConfiguration; +import org.sonar.server.computation.dbcleaner.ProjectPurgeTask; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.source.index.SourceLineIndexer; -import java.util.List; - import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration; public class DataCleanerStep implements ComputationStep { @@ -54,12 +52,10 @@ public class DataCleanerStep implements ComputationStep { Settings settings = projectSettingsFactory.newProjectSettings(session, projectId); PurgeConfiguration purgeConfiguration = newDefaultPurgeConfiguration(settings, projectId); - List<String> fileUuidsToDisable = purgeTask.findUuidsToDisable(session, projectId); purgeTask.purge(session, purgeConfiguration, settings); if (purgeConfiguration.maxLiveDateOfClosedIssues() != null) { issueIndex.deleteClosedIssuesOfProjectBefore(project.uuid(), purgeConfiguration.maxLiveDateOfClosedIssues()); - sourceLineIndexer.deleteByFiles(fileUuidsToDisable); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java new file mode 100644 index 00000000000..fb48b5cff61 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java @@ -0,0 +1,38 @@ +/* + * 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.dbcleaner; + +import org.sonar.api.ServerComponent; +import org.sonar.core.purge.PurgeListener; +import org.sonar.server.source.index.SourceLineIndexer; + +public class IndexPurgeListener implements PurgeListener, ServerComponent { + private final SourceLineIndexer sourceLineIndexer; + + public IndexPurgeListener(SourceLineIndexer sourceLineIndexer) { + this.sourceLineIndexer = sourceLineIndexer; + } + + @Override + public void onComponentDisabling(String uuid) { + sourceLineIndexer.deleteByFile(uuid); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTask.java index d6e13f36e37..d909c5548a5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTask.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTask.java @@ -26,24 +26,27 @@ import org.sonar.api.CoreProperties; import org.sonar.api.ServerComponent; import org.sonar.api.config.Settings; import org.sonar.api.utils.TimeUtils; -import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import org.sonar.core.persistence.DbSession; import org.sonar.core.purge.PurgeConfiguration; import org.sonar.core.purge.PurgeDao; +import org.sonar.core.purge.PurgeListener; import org.sonar.core.purge.PurgeProfiler; +import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import java.util.List; public class ProjectPurgeTask implements ServerComponent { private static final Logger LOG = LoggerFactory.getLogger(ProjectPurgeTask.class); private final PurgeProfiler profiler; + private final PurgeListener purgeListener; private final PurgeDao purgeDao; private final DefaultPeriodCleaner periodCleaner; - public ProjectPurgeTask(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) { + public ProjectPurgeTask(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler, PurgeListener purgeListener) { this.purgeDao = purgeDao; this.periodCleaner = periodCleaner; this.profiler = profiler; + this.purgeListener = purgeListener; } public ProjectPurgeTask purge(DbSession session, PurgeConfiguration configuration, Settings settings) { @@ -71,7 +74,7 @@ public class ProjectPurgeTask implements ServerComponent { private void doPurge(DbSession session, PurgeConfiguration configuration) { try { - purgeDao.purge(session, configuration); + purgeDao.purge(session, configuration, purgeListener); } catch (Exception e) { // purge errors must no fail the report analysis LOG.error("Fail to purge data [id=" + configuration.rootProjectId() + "]", e); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index a68960db2eb..0abd8100276 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -37,9 +37,6 @@ import org.sonar.api.utils.System2; import org.sonar.api.utils.UriReader; import org.sonar.api.utils.internal.TempFolderCleaner; import org.sonar.core.component.SnapshotPerspectives; -import org.sonar.server.computation.dbcleaner.DefaultPurgeTask; -import org.sonar.server.computation.dbcleaner.ProjectPurgeTask; -import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.config.Logback; import org.sonar.core.i18n.DefaultI18n; @@ -53,13 +50,7 @@ import org.sonar.core.measure.db.MeasureFilterDao; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.DaoUtils; -import org.sonar.core.persistence.DatabaseVersion; -import org.sonar.core.persistence.DefaultDatabase; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.persistence.PreviewDatabaseFactory; -import org.sonar.core.persistence.SemaphoreUpdater; -import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.persistence.*; import org.sonar.core.preview.PreviewCache; import org.sonar.core.profiling.Profiling; import org.sonar.core.purge.PurgeProfiler; @@ -85,11 +76,7 @@ import org.sonar.server.activity.index.ActivityNormalizer; import org.sonar.server.activity.ws.ActivitiesWebService; import org.sonar.server.activity.ws.ActivityMapping; import org.sonar.server.authentication.ws.AuthenticationWs; -import org.sonar.server.batch.BatchIndex; -import org.sonar.server.batch.BatchWs; -import org.sonar.server.batch.GlobalReferentialsAction; -import org.sonar.server.batch.ProjectReferentialsAction; -import org.sonar.server.batch.UploadReportAction; +import org.sonar.server.batch.*; import org.sonar.server.charts.ChartFactory; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentService; @@ -97,30 +84,14 @@ import org.sonar.server.component.DefaultComponentFinder; import org.sonar.server.component.DefaultRubyComponentService; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; -import org.sonar.server.component.ws.ComponentAppAction; -import org.sonar.server.component.ws.ComponentsWs; -import org.sonar.server.component.ws.EventsWs; -import org.sonar.server.component.ws.ProjectsWs; -import org.sonar.server.component.ws.ResourcesWs; -import org.sonar.server.computation.AnalysisReportQueue; -import org.sonar.server.computation.AnalysisReportTaskCleaner; -import org.sonar.server.computation.AnalysisReportTaskLauncher; -import org.sonar.server.computation.ComponentIndexationInDatabaseStep; -import org.sonar.server.computation.ComputationService; -import org.sonar.server.computation.ComputationStepRegistry; -import org.sonar.server.computation.DataCleanerStep; -import org.sonar.server.computation.DigestAnalysisReportStep; -import org.sonar.server.computation.IndexProjectIssuesStep; -import org.sonar.server.computation.InvalidatePreviewCacheStep; -import org.sonar.server.computation.SwitchSnapshotStep; -import org.sonar.server.computation.SynchronizeProjectPermissionsStep; +import org.sonar.server.component.ws.*; +import org.sonar.server.computation.*; import org.sonar.server.computation.db.AnalysisReportDao; -import org.sonar.server.computation.ws.ActiveAnalysisReportsAction; -import org.sonar.server.computation.ws.AnalysisReportHistorySearchAction; -import org.sonar.server.computation.ws.AnalysisReportWebService; -import org.sonar.server.computation.ws.ExperimentalAnalysisReportAction; -import org.sonar.server.computation.ws.ExperimentalAnalysisReportWebService; -import org.sonar.server.computation.ws.IsAnalysisReportQueueEmptyAction; +import org.sonar.server.computation.dbcleaner.DefaultPurgeTask; +import org.sonar.server.computation.dbcleaner.IndexPurgeListener; +import org.sonar.server.computation.dbcleaner.ProjectPurgeTask; +import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; +import org.sonar.server.computation.ws.*; import org.sonar.server.config.ws.PropertiesWs; import org.sonar.server.dashboard.db.DashboardDao; import org.sonar.server.dashboard.db.WidgetDao; @@ -132,14 +103,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.debt.DebtCharacteristicsXMLImporter; -import org.sonar.server.debt.DebtModelBackup; -import org.sonar.server.debt.DebtModelLookup; -import org.sonar.server.debt.DebtModelOperations; -import org.sonar.server.debt.DebtModelPluginRepository; -import org.sonar.server.debt.DebtModelService; -import org.sonar.server.debt.DebtModelXMLExporter; -import org.sonar.server.debt.DebtRulesXMLImporter; +import org.sonar.server.debt.*; import org.sonar.server.design.FileDesignWidget; import org.sonar.server.duplication.ws.DuplicationsJsonWriter; import org.sonar.server.duplication.ws.DuplicationsParser; @@ -147,31 +111,14 @@ import org.sonar.server.duplication.ws.DuplicationsWs; import org.sonar.server.es.EsClient; import org.sonar.server.es.IndexCreator; import org.sonar.server.es.IndexRegistry; -import org.sonar.server.issue.ActionService; -import org.sonar.server.issue.AssignAction; -import org.sonar.server.issue.CommentAction; -import org.sonar.server.issue.InternalRubyIssueService; -import org.sonar.server.issue.IssueBulkChangeService; -import org.sonar.server.issue.IssueChangelogFormatter; -import org.sonar.server.issue.IssueChangelogService; -import org.sonar.server.issue.IssueCommentService; -import org.sonar.server.issue.IssueQueryService; -import org.sonar.server.issue.IssueService; -import org.sonar.server.issue.PlanAction; -import org.sonar.server.issue.ServerIssueStorage; -import org.sonar.server.issue.SetSeverityAction; -import org.sonar.server.issue.TransitionAction; +import org.sonar.server.issue.*; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.actionplan.ActionPlanWs; import org.sonar.server.issue.db.IssueDao; import org.sonar.server.issue.filter.IssueFilterService; import org.sonar.server.issue.filter.IssueFilterWriter; import org.sonar.server.issue.filter.IssueFilterWs; -import org.sonar.server.issue.index.IssueAuthorizationIndexer; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.issue.index.IssueNormalizer; +import org.sonar.server.issue.index.*; import org.sonar.server.issue.ws.IssueActionsWriter; import org.sonar.server.issue.ws.IssueShowAction; import org.sonar.server.issue.ws.IssuesWs; @@ -193,117 +140,34 @@ import org.sonar.server.platform.ws.L10nWs; import org.sonar.server.platform.ws.RestartHandler; import org.sonar.server.platform.ws.ServerWs; import org.sonar.server.platform.ws.SystemWs; -import org.sonar.server.plugins.InstalledPluginReferentialFactory; -import org.sonar.server.plugins.PluginDownloader; -import org.sonar.server.plugins.ServerExtensionInstaller; -import org.sonar.server.plugins.ServerPluginJarInstaller; -import org.sonar.server.plugins.ServerPluginJarsInstaller; -import org.sonar.server.plugins.ServerPluginRepository; -import org.sonar.server.plugins.UpdateCenterClient; -import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.plugins.*; import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.RegisterQualityGates; -import org.sonar.server.qualitygate.ws.QGatesAppAction; -import org.sonar.server.qualitygate.ws.QGatesCopyAction; -import org.sonar.server.qualitygate.ws.QGatesCreateAction; -import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeselectAction; -import org.sonar.server.qualitygate.ws.QGatesDestroyAction; -import org.sonar.server.qualitygate.ws.QGatesListAction; -import org.sonar.server.qualitygate.ws.QGatesRenameAction; -import org.sonar.server.qualitygate.ws.QGatesSearchAction; -import org.sonar.server.qualitygate.ws.QGatesSelectAction; -import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesShowAction; -import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesWs; -import org.sonar.server.qualityprofile.BuiltInProfiles; -import org.sonar.server.qualityprofile.QProfileBackuper; -import org.sonar.server.qualityprofile.QProfileCopier; -import org.sonar.server.qualityprofile.QProfileExporters; -import org.sonar.server.qualityprofile.QProfileFactory; -import org.sonar.server.qualityprofile.QProfileLoader; -import org.sonar.server.qualityprofile.QProfileLookup; -import org.sonar.server.qualityprofile.QProfileProjectLookup; -import org.sonar.server.qualityprofile.QProfileProjectOperations; -import org.sonar.server.qualityprofile.QProfileReset; -import org.sonar.server.qualityprofile.QProfileService; -import org.sonar.server.qualityprofile.QProfiles; -import org.sonar.server.qualityprofile.RegisterQualityProfiles; -import org.sonar.server.qualityprofile.RuleActivator; -import org.sonar.server.qualityprofile.RuleActivatorContextFactory; +import org.sonar.server.qualitygate.ws.*; +import org.sonar.server.qualityprofile.*; import org.sonar.server.qualityprofile.db.ActiveRuleDao; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; -import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; -import org.sonar.server.qualityprofile.ws.ProfilesWs; -import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction; -import org.sonar.server.qualityprofile.ws.QProfilesWs; -import org.sonar.server.qualityprofile.ws.RuleActivationActions; -import org.sonar.server.rule.DefaultRuleFinder; -import org.sonar.server.rule.DeprecatedRulesDefinitionLoader; -import org.sonar.server.rule.RegisterRules; -import org.sonar.server.rule.RubyRuleService; -import org.sonar.server.rule.RuleCreator; -import org.sonar.server.rule.RuleDefinitionsLoader; -import org.sonar.server.rule.RuleDeleter; -import org.sonar.server.rule.RuleOperations; -import org.sonar.server.rule.RuleRepositories; -import org.sonar.server.rule.RuleService; -import org.sonar.server.rule.RuleUpdater; +import org.sonar.server.qualityprofile.ws.*; +import org.sonar.server.rule.*; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleNormalizer; -import org.sonar.server.rule.ws.ActiveRuleCompleter; -import org.sonar.server.rule.ws.AppAction; -import org.sonar.server.rule.ws.DeleteAction; -import org.sonar.server.rule.ws.RuleMapping; -import org.sonar.server.rule.ws.RulesWebService; -import org.sonar.server.rule.ws.SearchAction; -import org.sonar.server.rule.ws.TagsAction; -import org.sonar.server.rule.ws.UpdateAction; -import org.sonar.server.search.IndexClient; -import org.sonar.server.search.IndexQueue; -import org.sonar.server.search.IndexSynchronizer; -import org.sonar.server.search.SearchClient; -import org.sonar.server.search.SearchHealth; +import org.sonar.server.rule.ws.*; +import org.sonar.server.search.*; import org.sonar.server.source.HtmlSourceDecorator; import org.sonar.server.source.IndexSourceLinesStep; import org.sonar.server.source.SourceService; import org.sonar.server.source.index.SourceLineIndex; import org.sonar.server.source.index.SourceLineIndexDefinition; import org.sonar.server.source.index.SourceLineIndexer; -import org.sonar.server.source.ws.HashAction; -import org.sonar.server.source.ws.LinesAction; -import org.sonar.server.source.ws.RawAction; -import org.sonar.server.source.ws.ScmAction; -import org.sonar.server.source.ws.ScmWriter; +import org.sonar.server.source.ws.*; import org.sonar.server.source.ws.ShowAction; -import org.sonar.server.source.ws.SourcesWs; -import org.sonar.server.startup.CleanPreviewAnalysisCache; -import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; -import org.sonar.server.startup.GeneratePluginIndex; -import org.sonar.server.startup.JdbcDriverDeployer; -import org.sonar.server.startup.LogServerId; -import org.sonar.server.startup.RegisterDashboards; -import org.sonar.server.startup.RegisterDebtModel; -import org.sonar.server.startup.RegisterMetrics; -import org.sonar.server.startup.RegisterNewMeasureFilters; -import org.sonar.server.startup.RegisterPermissionTemplates; -import org.sonar.server.startup.RegisterServletFilters; -import org.sonar.server.startup.RenameDeprecatedPropertyKeys; -import org.sonar.server.startup.ServerMetadataPersister; +import org.sonar.server.startup.*; import org.sonar.server.test.CoverageService; -import org.sonar.server.test.ws.CoverageShowAction; -import org.sonar.server.test.ws.CoverageWs; -import org.sonar.server.test.ws.TestsCoveredFilesAction; -import org.sonar.server.test.ws.TestsShowAction; -import org.sonar.server.test.ws.TestsTestCasesAction; -import org.sonar.server.test.ws.TestsWs; +import org.sonar.server.test.ws.*; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; import org.sonar.server.ui.JRubyI18n; @@ -311,23 +175,12 @@ import org.sonar.server.ui.JRubyProfiling; import org.sonar.server.ui.PageDecorations; import org.sonar.server.ui.Views; import org.sonar.server.updatecenter.ws.UpdateCenterWs; -import org.sonar.server.user.DefaultUserService; -import org.sonar.server.user.DoPrivileged; -import org.sonar.server.user.GroupMembershipFinder; -import org.sonar.server.user.GroupMembershipService; -import org.sonar.server.user.NewUserNotifier; -import org.sonar.server.user.SecurityRealmFactory; +import org.sonar.server.user.*; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.ws.FavoritesWs; import org.sonar.server.user.ws.UserPropertiesWs; import org.sonar.server.user.ws.UsersWs; -import org.sonar.server.util.BooleanTypeValidation; -import org.sonar.server.util.FloatTypeValidation; -import org.sonar.server.util.IntegerTypeValidation; -import org.sonar.server.util.StringListTypeValidation; -import org.sonar.server.util.StringTypeValidation; -import org.sonar.server.util.TextTypeValidation; -import org.sonar.server.util.TypeValidations; +import org.sonar.server.util.*; import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.WebServiceEngine; @@ -767,6 +620,7 @@ class ServerComponents { pico.addSingleton(DefaultPurgeTask.class); pico.addSingleton(ProjectPurgeTask.class); pico.addSingleton(ProjectSettingsFactory.class); + pico.addSingleton(IndexPurgeListener.class); for (Object components : level4AddedComponents) { pico.addSingleton(components); diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java index 6809c2fd263..131fee0d30e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java @@ -30,7 +30,6 @@ import org.sonar.server.es.EsClient; import java.sql.Connection; import java.util.Iterator; -import java.util.List; import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_FILE_UUID; import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_PROJECT_UUID; @@ -96,16 +95,16 @@ public class SourceLineIndexer extends BaseIndexer { private void deleteLinesFromFileAbove(String fileUuid, int lastLine) { esClient.prepareDeleteByQuery(SourceLineIndexDefinition.INDEX) .setTypes(SourceLineIndexDefinition.TYPE) - .setQuery(QueryBuilders.boolQuery() - .must(QueryBuilders.termQuery(FIELD_FILE_UUID, fileUuid)) - .must(QueryBuilders.rangeQuery(SourceLineIndexDefinition.FIELD_LINE).gt(lastLine)) - ).get(); + .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.boolFilter() + .must(FilterBuilders.termFilter(FIELD_FILE_UUID, fileUuid).cache(false)) + .must(FilterBuilders.rangeFilter(SourceLineIndexDefinition.FIELD_LINE).gt(lastLine).cache(false)) + )).get(); } - public void deleteByFiles(List<String> uuids) { + public void deleteByFile(String fileUuid) { esClient.prepareDeleteByQuery(SourceLineIndexDefinition.INDEX) .setTypes(SourceLineIndexDefinition.TYPE) - .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.termsFilter(FIELD_FILE_UUID, uuids).cache(false))) + .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.termFilter(FIELD_FILE_UUID, fileUuid).cache(false))) .get(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java new file mode 100644 index 00000000000..5f34d84010e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java @@ -0,0 +1,41 @@ +/* + * 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.dbcleaner; + +import org.junit.Test; +import org.sonar.server.source.index.SourceLineIndexer; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class IndexPurgeListenerTest { + + @Test + public void call_source_line_indexer() { + SourceLineIndexer indexer = mock(SourceLineIndexer.class); + IndexPurgeListener sut = new IndexPurgeListener(indexer); + + sut.onComponentDisabling("123456"); + + verify(indexer).deleteByFile("123456"); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTaskTest.java index 74cafe743f7..25c4c7cca8f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTaskTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTaskTest.java @@ -25,11 +25,12 @@ import org.junit.Test; import org.slf4j.Logger; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; -import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import org.sonar.core.persistence.DbSession; import org.sonar.core.purge.PurgeConfiguration; import org.sonar.core.purge.PurgeDao; +import org.sonar.core.purge.PurgeListener; import org.sonar.core.purge.PurgeProfiler; +import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; @@ -41,14 +42,16 @@ public class ProjectPurgeTaskTest { private PurgeDao dao; private PurgeProfiler profiler; private DefaultPeriodCleaner periodCleaner; + private PurgeListener purgeListener; @Before public void before() throws Exception { this.dao = mock(PurgeDao.class); this.profiler = mock(PurgeProfiler.class); this.periodCleaner = mock(DefaultPeriodCleaner.class); + this.purgeListener = mock(PurgeListener.class); - this.sut = new ProjectPurgeTask(dao, periodCleaner, profiler); + this.sut = new ProjectPurgeTask(dao, periodCleaner, profiler, purgeListener); } @Test @@ -73,11 +76,11 @@ public class ProjectPurgeTaskTest { @Test public void if_dao_purge_fails_it_should_not_interrupt_program_execution() throws Exception { - doThrow(RuntimeException.class).when(dao).purge(any(DbSession.class), any(PurgeConfiguration.class)); + doThrow(RuntimeException.class).when(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class)); sut.purge(mock(DbSession.class), mock(PurgeConfiguration.class), mock(Settings.class)); - verify(dao, times(1)).purge(any(DbSession.class), any(PurgeConfiguration.class)); + verify(dao, times(1)).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class)); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java index d0731a06734..cc195db8434 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java @@ -22,7 +22,6 @@ package org.sonar.server.source.index; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.search.SearchRequestBuilder; @@ -118,12 +117,12 @@ public class SourceLineIndexerTest { } @Test - public void delete_file_uuids() throws Exception { + public void delete_file_uuid() throws Exception { addSource("line2.json"); addSource("line3.json"); addSource("line2_other_file.json"); - indexer.deleteByFiles(Lists.newArrayList("efgh")); + indexer.deleteByFile("efgh"); List<SearchHit> hits = getDocuments(); Map<String, Object> document = hits.get(0).getSource(); 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 9eb298082ab..71dc5863e15 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 @@ -54,10 +54,10 @@ public class PurgeDao { this.system2 = system2; } - public PurgeDao purge(PurgeConfiguration conf) { + public PurgeDao purge(PurgeConfiguration conf, PurgeListener purgeListener) { DbSession session = mybatis.openSession(true); try { - purge(session, conf); + purge(session, conf, purgeListener); session.commit(); } finally { MyBatis.closeQuietly(session); @@ -65,7 +65,7 @@ public class PurgeDao { return this; } - public void purge(DbSession session, PurgeConfiguration conf) { + public void purge(DbSession session, PurgeConfiguration conf, PurgeListener purgeListener) { PurgeMapper mapper = session.getMapper(PurgeMapper.class); PurgeCommands commands = new PurgeCommands(session, mapper, profiler); List<ResourceDto> projects = getProjects(conf.rootProjectId(), session); @@ -75,7 +75,7 @@ public class PurgeDao { purge(project, conf.scopesWithoutHistoricalData(), commands); } for (ResourceDto project : projects) { - disableOrphanResources(project, session, mapper); + disableOrphanResources(project, session, mapper, purgeListener); } deleteOldClosedIssues(conf, mapper); } @@ -130,13 +130,14 @@ public class PurgeDao { } } - private void disableOrphanResources(final ResourceDto project, final SqlSession session, final PurgeMapper purgeMapper) { + private void disableOrphanResources(final ResourceDto project, final SqlSession session, final PurgeMapper purgeMapper, final PurgeListener purgeListener) { session.select("org.sonar.core.purge.PurgeMapper.selectResourceIdsToDisable", project.getId(), new ResultHandler() { @Override public void handleResult(ResultContext resultContext) { IdUuidPair resourceIdUuid = (IdUuidPair) resultContext.getResultObject(); if (resourceIdUuid.getId() != null) { disableResource(resourceIdUuid, purgeMapper); + purgeListener.onComponentDisabling(resourceIdUuid.getUuid()); } } }); diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeListener.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeListener.java new file mode 100644 index 00000000000..055b259a221 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeListener.java @@ -0,0 +1,33 @@ +/* + * 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.purge; + +public interface PurgeListener { + + PurgeListener EMPTY = new PurgeListener() { + @Override + public void onComponentDisabling(String uuid) { + // do nothing + } + }; + + void onComponentDisabling(String uuid); +} diff --git a/sonar-core/src/main/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTask.java b/sonar-core/src/main/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTask.java index 188164e55fc..df991fe48a9 100644 --- a/sonar-core/src/main/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTask.java +++ b/sonar-core/src/main/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTask.java @@ -27,14 +27,11 @@ import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.TimeUtils; -import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; -import org.sonar.core.purge.IdUuidPair; -import org.sonar.core.purge.PurgeConfiguration; -import org.sonar.core.purge.PurgeDao; -import org.sonar.core.purge.PurgeProfiler; +import org.sonar.core.purge.*; import org.sonar.core.resource.ResourceDao; import org.sonar.core.resource.ResourceDto; import org.sonar.plugins.dbcleaner.api.PurgeTask; +import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration; @@ -98,7 +95,7 @@ public class DefaultPurgeTask implements PurgeTask { private void doPurge(long resourceId) { try { - purgeDao.purge(newPurgeConfigurationOnResource(resourceId)); + purgeDao.purge(newPurgeConfigurationOnResource(resourceId), PurgeListener.EMPTY); } catch (Exception e) { // purge errors must no fail the report analysis LOG.error("Fail to purge data [id=" + resourceId + "]", e); diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java index 8487e4076aa..3c1e080a25c 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java @@ -68,35 +68,35 @@ public class PurgeDaoTest extends AbstractDaoTestCase { @Test public void shouldDeleteAbortedBuilds() { setupData("shouldDeleteAbortedBuilds"); - sut.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30), PurgeListener.EMPTY); checkTables("shouldDeleteAbortedBuilds", "snapshots"); } @Test public void should_purge_project() { setupData("shouldPurgeProject"); - sut.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30), PurgeListener.EMPTY); checkTables("shouldPurgeProject", "projects", "snapshots"); } @Test public void delete_file_sources_of_disabled_resources() { setupData("delete_file_sources_of_disabled_resources"); - sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2), PurgeListener.EMPTY); checkTables("delete_file_sources_of_disabled_resources", "file_sources"); } @Test public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() { setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles"); - sut.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30)); + sut.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY); checkTables("shouldDeleteHistoricalDataOfDirectoriesAndFiles", "projects", "snapshots"); } @Test public void disable_resources_without_last_snapshot() { setupData("disable_resources_without_last_snapshot"); - sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2), PurgeListener.EMPTY); checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues"); } @@ -131,14 +131,14 @@ public class PurgeDaoTest extends AbstractDaoTestCase { @Test public void should_delete_old_closed_issues() { setupData("should_delete_old_closed_issues"); - sut.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30), PurgeListener.EMPTY); checkTables("should_delete_old_closed_issues", "issues", "issue_changes"); } @Test public void should_delete_all_closed_issues() { setupData("should_delete_all_closed_issues"); - sut.purge(new PurgeConfiguration(1L, new String[0], 0)); + sut.purge(new PurgeConfiguration(1L, new String[0], 0), PurgeListener.EMPTY); checkTables("should_delete_all_closed_issues", "issues", "issue_changes"); } diff --git a/sonar-core/src/test/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTaskTest.java b/sonar-core/src/test/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTaskTest.java index 1ca4ffef571..11060eebf10 100644 --- a/sonar-core/src/test/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTaskTest.java +++ b/sonar-core/src/test/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTaskTest.java @@ -29,11 +29,8 @@ import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.Settings; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; +import org.sonar.core.purge.*; import org.sonar.server.computation.dbcleaner.period.DefaultPeriodCleaner; -import org.sonar.core.purge.IdUuidPair; -import org.sonar.core.purge.PurgeConfiguration; -import org.sonar.core.purge.PurgeDao; -import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.resource.ResourceDao; import org.sonar.core.resource.ResourceDto; @@ -80,7 +77,7 @@ public class DefaultPurgeTaskTest { PurgeConfiguration conf = (PurgeConfiguration) o; return conf.rootProjectId() == 1L && conf.scopesWithoutHistoricalData().length == 1 && conf.scopesWithoutHistoricalData()[0].equals(Scopes.FILE); } - })); + }), any(PurgeListener.class)); } @Test @@ -100,25 +97,25 @@ public class DefaultPurgeTaskTest { conf.scopesWithoutHistoricalData()[0].equals(Scopes.DIRECTORY) && conf.scopesWithoutHistoricalData()[1].equals(Scopes.FILE); } - })); + }), any(PurgeListener.class)); } @Test public void shouldNotFailOnErrors() { PurgeDao purgeDao = mock(PurgeDao.class); - when(purgeDao.purge(any(PurgeConfiguration.class))).thenThrow(new RuntimeException()); + when(purgeDao.purge(any(PurgeConfiguration.class),any(PurgeListener.class))).thenThrow(new RuntimeException()); DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, resourceDao, new Settings(), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class)); task.purge(1L); - verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class)); + verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class), any(PurgeListener.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()); + when(purgeDao.purge(conf, PurgeListener.EMPTY)).thenThrow(new RuntimeException()); Settings settings = new Settings(new PropertyDefinitions(DataCleanerProperties.all())); settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true); PurgeProfiler profiler = mock(PurgeProfiler.class); |