Skip to content

Commit

Permalink
SONAR-6589 make BatchReportReader a dependency of ComputationSteps
Browse files Browse the repository at this point in the history
move batch zip file extraction to new class ReportExtractor
  • Loading branch information
sns-seb committed Jun 1, 2015
1 parent d7f6c4e commit be8707e
Show file tree
Hide file tree
Showing 46 changed files with 664 additions and 421 deletions.
Expand Up @@ -76,7 +76,7 @@ private void persistFileSources() {


long start = System.currentTimeMillis(); long start = System.currentTimeMillis();


PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, dbComponentsRefCache); PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, dbComponentsRefCache, reportReader);
step.execute(new ComputationContext(reportReader, "PROJECT_KEY", new Settings(), dbClient, ComponentTreeBuilders.from(DumbComponent.DUMB_PROJECT), step.execute(new ComputationContext(reportReader, "PROJECT_KEY", new Settings(), dbClient, ComponentTreeBuilders.from(DumbComponent.DUMB_PROJECT),
mock(LanguageRepository.class))); mock(LanguageRepository.class)));


Expand Down
Expand Up @@ -19,10 +19,16 @@
*/ */
package org.sonar.server.computation; package org.sonar.server.computation;


import java.util.Arrays;
import java.util.List;
import org.sonar.core.issue.db.UpdateConflictResolver; import org.sonar.core.issue.db.UpdateConflictResolver;
import org.sonar.core.platform.ComponentContainer; import org.sonar.core.platform.ComponentContainer;
import org.sonar.server.computation.activity.CEActivityManager;
import org.sonar.server.computation.batch.CEBatchReportReader;
import org.sonar.server.computation.batch.ReportExtractor;
import org.sonar.server.computation.component.DbComponentsRefCache; import org.sonar.server.computation.component.DbComponentsRefCache;
import org.sonar.server.computation.component.ProjectSettingsRepository; import org.sonar.server.computation.component.ProjectSettingsRepository;
import org.sonar.server.computation.container.CEContainer;
import org.sonar.server.computation.issue.IssueCache; import org.sonar.server.computation.issue.IssueCache;
import org.sonar.server.computation.issue.IssueComputation; import org.sonar.server.computation.issue.IssueComputation;
import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.issue.RuleCache;
Expand All @@ -36,9 +42,6 @@
import org.sonar.server.platform.Platform; import org.sonar.server.platform.Platform;
import org.sonar.server.view.index.ViewIndex; import org.sonar.server.view.index.ViewIndex;


import java.util.Arrays;
import java.util.List;

public class ComputationContainer { public class ComputationContainer {


/** /**
Expand All @@ -47,14 +50,15 @@ public class ComputationContainer {
*/ */
static List componentClasses() { static List componentClasses() {
return Arrays.asList( return Arrays.asList(
// context-scope repositories CEActivityManager.class,
ReportExtractor.class,
CEBatchReportReader.class,

// repositories
PlatformLanguageRepository.class, PlatformLanguageRepository.class,
ProjectSettingsRepository.class, ProjectSettingsRepository.class,


ComputationService.class, // component caches
ComputationSteps.class,

// component cache
DbComponentsRefCache.class, DbComponentsRefCache.class,


// issues // issues
Expand All @@ -74,17 +78,20 @@ static List componentClasses() {


public void execute(ReportQueue.Item item) { public void execute(ReportQueue.Item item) {
ComponentContainer container = Platform.getInstance().getContainer(); ComponentContainer container = Platform.getInstance().getContainer();
ComponentContainer child = container.createChild();
child.addSingletons(componentClasses()); ComponentContainer ceContainer = new CEContainer(container);
child.addSingletons(ComputationSteps.orderedStepClasses()); ceContainer.add(ceContainer);
child.startComponents(); ceContainer.add(item);
ceContainer.addSingletons(componentClasses());
ceContainer.addSingletons(ComputationSteps.orderedStepClasses());
try { try {
child.getComponentByType(ComputationService.class).process(item); ceContainer.getComponentByType(ComputationService.class).process();
} finally { } finally {
child.stopComponents(); ceContainer.stopComponents();
// TODO not possible to have multiple children -> will be // TODO not possible to have multiple children -> will be
// a problem when we will have multiple concurrent computation workers // a problem when we will have multiple concurrent computation workers
container.removeChild(); container.removeChild();
} }
} }

} }
Expand Up @@ -17,37 +17,22 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */

package org.sonar.server.computation; package org.sonar.server.computation;


import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import java.io.File;
import java.io.IOException;
import javax.annotation.CheckForNull;
import org.apache.commons.io.FileUtils;
import org.sonar.api.server.ServerSide; import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.System2; import org.sonar.api.utils.System2;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler; import org.sonar.api.utils.log.Profiler;
import org.sonar.core.component.ComponentDto; import org.sonar.server.computation.activity.CEActivityManager;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.batch.FileBatchReportReader;
import org.sonar.server.computation.component.ComponentTreeBuilders; import org.sonar.server.computation.component.ComponentTreeBuilders;
import org.sonar.server.computation.language.LanguageRepository; import org.sonar.server.computation.language.LanguageRepository;
import org.sonar.server.computation.step.ComputationStep; import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps; import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient; import org.sonar.server.db.DbClient;


import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
import static org.sonar.api.utils.DateUtils.longToDate;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.FAILED; import static org.sonar.core.computation.db.AnalysisReportDto.Status.FAILED;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.SUCCESS; import static org.sonar.core.computation.db.AnalysisReportDto.Status.SUCCESS;


Expand All @@ -56,33 +41,35 @@ public class ComputationService {


private static final Logger LOG = Loggers.get(ComputationService.class); private static final Logger LOG = Loggers.get(ComputationService.class);


private final DbClient dbClient; private final ReportQueue.Item item;
private final ComputationSteps steps; private final ComputationSteps steps;
private final ActivityService activityService; private final BatchReportReader reportReader;
private final TempFolder tempFolder; private final CEActivityManager activityManager;
private final System2 system; private final System2 system;
private final DbClient dbClient;
private final LanguageRepository languageRepository; private final LanguageRepository languageRepository;


public ComputationService(DbClient dbClient, ComputationSteps steps, ActivityService activityService, public ComputationService(ReportQueue.Item item, ComputationSteps steps, CEActivityManager activityManager, System2 system,
TempFolder tempFolder, System2 system, LanguageRepository languageRepository) { BatchReportReader reportReader, DbClient dbClient, LanguageRepository languageRepository) {
this.dbClient = dbClient; this.item = item;
this.steps = steps; this.steps = steps;
this.activityService = activityService; this.reportReader = reportReader;
this.tempFolder = tempFolder; this.activityManager = activityManager;
this.system = system; this.system = system;
this.dbClient = dbClient;
this.languageRepository = languageRepository; this.languageRepository = languageRepository;
} }


public void process(ReportQueue.Item item) { public void process() {
String projectKey = item.dto.getProjectKey(); String projectKey = item.dto.getProjectKey();
Profiler profiler = Profiler.create(LOG).startDebug(String.format( Profiler profiler = Profiler.create(LOG).startDebug(
"Analysis of project %s (report %d)", projectKey, item.dto.getId())); String.format("Analysis of project %s (report %d)", projectKey, item.dto.getId())
);


try { try {
File reportDir = extractReportInDir(item); ComputationContext context = new ComputationContext(reportReader, null, null, dbClient, ComponentTreeBuilders.from(reportReader), languageRepository);
BatchReportReader reader = new FileBatchReportReader(new org.sonar.batch.protocol.output.BatchReportReader(reportDir));
ComputationContext context = new ComputationContext(reader, null, null, dbClient, ComponentTreeBuilders.from(reader), languageRepository); for (ComputationStep step : steps.instances()) {
for (ComputationStep step : steps.orderedSteps()) {
Profiler stepProfiler = Profiler.createIfDebug(LOG).startDebug(step.getDescription()); Profiler stepProfiler = Profiler.createIfDebug(LOG).startDebug(step.getDescription());
step.execute(context); step.execute(context);
stepProfiler.stopDebug(); stepProfiler.stopDebug();
Expand All @@ -93,54 +80,8 @@ public void process(ReportQueue.Item item) {
throw Throwables.propagate(e); throw Throwables.propagate(e);
} finally { } finally {
item.dto.setFinishedAt(system.now()); item.dto.setFinishedAt(system.now());
saveActivity(item.dto); activityManager.saveActivity(item.dto);
profiler.stopInfo(); profiler.stopInfo();
} }
} }

private File extractReportInDir(ReportQueue.Item item) {
File dir = tempFolder.newDir();
try {
Profiler profiler = Profiler.createIfDebug(LOG).start();
ZipUtils.unzip(item.zipFile, dir);
if (profiler.isDebugEnabled()) {
String message = String.format("Report extracted | size=%s | project=%s",
FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), item.dto.getProjectKey());
profiler.stopDebug(message);
}
return dir;
} catch (IOException e) {
throw new IllegalStateException(String.format("Fail to unzip %s into %s", item.zipFile, dir), e);
}
}

private void saveActivity(AnalysisReportDto report) {
ComponentDto project = loadProject(report.getProjectKey());
Activity activity = new Activity();
activity.setType(Activity.Type.ANALYSIS_REPORT);
activity.setAction("LOG_ANALYSIS_REPORT");
activity
.setData("key", String.valueOf(report.getId()))
.setData("projectKey", report.getProjectKey())
.setData("status", String.valueOf(report.getStatus()))
.setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
.setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
.setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
if (project != null) {
activity
.setData("projectName", project.name())
.setData("projectUuid", project.uuid());
}
activityService.save(activity);
}

@CheckForNull
private ComponentDto loadProject(String projectKey) {
DbSession session = dbClient.openSession(false);
try {
return dbClient.componentDao().selectNullableByKey(session, projectKey);
} finally {
MyBatis.closeQuietly(session);
}
}
} }
@@ -0,0 +1,72 @@
/*
* 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.activity;

import javax.annotation.CheckForNull;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.db.DbClient;

import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
import static org.sonar.api.utils.DateUtils.longToDate;

public class CEActivityManager {
private final ActivityService activityService;
private final DbClient dbClient;

public CEActivityManager(ActivityService activityService, DbClient dbClient) {
this.activityService = activityService;
this.dbClient = dbClient;
}

public void saveActivity(AnalysisReportDto report) {
ComponentDto project = loadProject(report.getProjectKey());
Activity activity = new Activity();
activity.setType(Activity.Type.ANALYSIS_REPORT);
activity.setAction("LOG_ANALYSIS_REPORT");
activity
.setData("key", String.valueOf(report.getId()))
.setData("projectKey", report.getProjectKey())
.setData("status", String.valueOf(report.getStatus()))
.setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
.setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
.setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
if (project != null) {
activity
.setData("projectName", project.name())
.setData("projectUuid", project.uuid());
}
activityService.save(activity);
}

@CheckForNull
private ComponentDto loadProject(String projectKey) {
DbSession session = dbClient.openSession(false);
try {
return dbClient.componentDao().selectNullableByKey(session, projectKey);
} finally {
MyBatis.closeQuietly(session);
}
}
}
@@ -0,0 +1,24 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

@ParametersAreNonnullByDefault
package org.sonar.server.computation.activity;

import javax.annotation.ParametersAreNonnullByDefault;
Expand Up @@ -32,13 +32,14 @@
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator; import org.apache.commons.io.LineIterator;
import org.sonar.batch.protocol.output.BatchReport; import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.server.computation.ReportQueue;
import org.sonar.server.util.CloseableIterator; import org.sonar.server.util.CloseableIterator;


public class FileBatchReportReader implements BatchReportReader { public class CEBatchReportReader implements BatchReportReader {
private final org.sonar.batch.protocol.output.BatchReportReader delegate; private final org.sonar.batch.protocol.output.BatchReportReader delegate;


public FileBatchReportReader(org.sonar.batch.protocol.output.BatchReportReader delegate) { public CEBatchReportReader(ReportExtractor reportExtractor, ReportQueue.Item item) {
this.delegate = delegate; this.delegate = new org.sonar.batch.protocol.output.BatchReportReader(reportExtractor.extractReportInDir(item));
} }


@Override @Override
Expand Down

0 comments on commit be8707e

Please sign in to comment.