]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5804 fix source lines purge of multi module projects
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Wed, 3 Dec 2014 17:42:09 +0000 (18:42 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Wed, 3 Dec 2014 17:51:45 +0000 (18:51 +0100)
13 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTask.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java
server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectPurgeTaskTest.java
server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeListener.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTask.java
sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
sonar-core/src/test/java/org/sonar/server/computation/dbcleaner/DefaultPurgeTaskTest.java

index bcb7b7f4454f63352394b4651928ebaea7ee7f45..1bb8802150eff76989b8217e51ec82f40c51d41f 100644 (file)
@@ -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 (file)
index 0000000..fb48b5c
--- /dev/null
@@ -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);
+  }
+}
index d6e13f36e3786dbaa02c3a960664af35a6d5d714..d909c5548a51cb8d637dd730a49604dc1fd49d71 100644 (file)
@@ -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);
index a68960db2ebca51f5018e35d82617bac72ff3221..0abd810027641936afd9d2e3599ca8e1d6756355 100644 (file)
@@ -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);
index 6809c2fd263f1ec588e491ebe2d85f0e27bcc6fb..131fee0d30e572e84c7a528813d0c37ba6885484 100644 (file)
@@ -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 (file)
index 0000000..5f34d84
--- /dev/null
@@ -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");
+  }
+
+}
index 74cafe743f70a969e3bfbac0689c0b5b7284d415..25c4c7cca8f3f067896eb79900b6ca0affd86a03 100644 (file)
@@ -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
index d0731a067345c8d3c133eed246126301c515aea2..cc195db8434908b6a1d4b8b86be3bc76b398fb93 100644 (file)
@@ -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();
index 9eb298082ab0cec52782778ce1272314634ec159..71dc5863e1582bab4a36fbe7343480ec216766e4 100644 (file)
@@ -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 (file)
index 0000000..055b259
--- /dev/null
@@ -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);
+}
index 188164e55fcef3f95b16f4ae1af573f9b5b6c32e..df991fe48a92ff6f3aacfb2dd30be742330f1224 100644 (file)
@@ -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);
index 8487e4076aaefefce7e51dea4e779dc5bbb022fc..3c1e080a25c41c85b78cca754c5d34d5c8aa901f 100644 (file)
@@ -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");
   }
 
index 1ca4ffef571dbefe5f2bca4d3a19832869d788f4..11060eebf10a7d988ab238166894b5372d2f169b 100644 (file)
@@ -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);