Quellcode durchsuchen

SONAR-5433 Do not loose exception when indexing FS

tags/4.5-RC1
Julien HENRY vor 10 Jahren
Ursprung
Commit
87dbec69ee

+ 36
- 18
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java Datei anzeigen

import org.sonar.api.utils.MessageException; import org.sonar.api.utils.MessageException;


import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;


/** /**
* Index input files into {@link InputFileCache}. * Index input files into {@link InputFileCache}.
private final ExclusionFilters exclusionFilters; private final ExclusionFilters exclusionFilters;
private final InputFileBuilderFactory inputFileBuilderFactory; private final InputFileBuilderFactory inputFileBuilderFactory;


private ExecutorService executor;

public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory, public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
InputFileCache cache, ProjectDefinition def) { InputFileCache cache, ProjectDefinition def) {
this(filters, exclusionFilters, inputFileBuilderFactory, cache, !def.getSubProjects().isEmpty()); this(filters, exclusionFilters, inputFileBuilderFactory, cache, !def.getSubProjects().isEmpty());


Progress progress = new Progress(fileCache.byModule(fileSystem.moduleKey())); Progress progress = new Progress(fileCache.byModule(fileSystem.moduleKey()));


executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);

InputFileBuilder inputFileBuilder = inputFileBuilderFactory.create(fileSystem); InputFileBuilder inputFileBuilder = inputFileBuilderFactory.create(fileSystem);
indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.sources(), InputFile.Type.MAIN); indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.sources(), InputFile.Type.MAIN);
indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.tests(), InputFile.Type.TEST); indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.tests(), InputFile.Type.TEST);


executor.shutdown();
try {
while (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
LOG.debug("{} files indexed...", progress.count());
}
} catch (InterruptedException e) {
throw new IllegalStateException("FileIndexer was interrupted", e);
}
indexAllConcurrently(progress);


// Populate FS in a synchronous way because PersistIt Exchange is not concurrent // Populate FS in a synchronous way because PersistIt Exchange is not concurrent
for (InputFile indexed : progress.indexed) { for (InputFile indexed : progress.indexed) {


} }


private void indexAllConcurrently(Progress progress) {
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
try {
List<Future<Void>> all = executor.invokeAll(progress.indexingTasks);
for (Future<Void> future : all) {
future.get();
}
} catch (InterruptedException e) {
throw new IllegalStateException("FileIndexer was interrupted", e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else {
throw new IllegalStateException("Error during file indexing", e);
}
}
executor.shutdown();
}

private void indexFiles(DefaultModuleFileSystem fileSystem, Progress progress, InputFileBuilder inputFileBuilder, List<File> sources, InputFile.Type type) { private void indexFiles(DefaultModuleFileSystem fileSystem, Progress progress, InputFileBuilder inputFileBuilder, List<File> sources, InputFile.Type type) {
for (File dirOrFile : sources) { for (File dirOrFile : sources) {
if (dirOrFile.isDirectory()) { if (dirOrFile.isDirectory()) {
private void indexFile(final InputFileBuilder inputFileBuilder, final DefaultModuleFileSystem fs, private void indexFile(final InputFileBuilder inputFileBuilder, final DefaultModuleFileSystem fs,
final Progress status, final DeprecatedDefaultInputFile inputFile, final InputFile.Type type) { final Progress status, final DeprecatedDefaultInputFile inputFile, final InputFile.Type type) {


Runnable worker = new Runnable() {
Callable<Void> task = new Callable<Void>() {


@Override @Override
public void run() {
public Void call() throws Exception {
InputFile completedFile = inputFileBuilder.complete(inputFile, type); InputFile completedFile = inputFileBuilder.complete(inputFile, type);
if (completedFile != null && accept(completedFile)) { if (completedFile != null && accept(completedFile)) {
status.markAsIndexed(completedFile);
status.markAsIndexed(inputFile);
} }
return null;
} }
}; };
executor.execute(worker);

status.planForIndexing(task);
} }


private boolean accept(InputFile inputFile) { private boolean accept(InputFile inputFile) {
private static class Progress { private static class Progress {
private final Set<InputFile> removed; private final Set<InputFile> removed;
private final Set<InputFile> indexed; private final Set<InputFile> indexed;
private final List<Callable<Void>> indexingTasks;


Progress(Iterable<InputFile> removed) { Progress(Iterable<InputFile> removed) {
this.removed = Sets.newHashSet(removed); this.removed = Sets.newHashSet(removed);
this.indexed = new HashSet<InputFile>(); this.indexed = new HashSet<InputFile>();
this.indexingTasks = new ArrayList<Callable<Void>>();
}

void planForIndexing(Callable<Void> indexingTask) {
this.indexingTasks.add(indexingTask);
} }


synchronized void markAsIndexed(InputFile inputFile) { synchronized void markAsIndexed(InputFile inputFile) {

+ 25
- 1
sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java Datei anzeigen

import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.mediumtest.AnalyzerMediumTester; import org.sonar.batch.mediumtest.AnalyzerMediumTester;
import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult; import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult;
import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin; import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;


public class FileSystemMediumTest { public class FileSystemMediumTest {


@org.junit.Rule
@Rule
public TemporaryFolder temp = new TemporaryFolder(); public TemporaryFolder temp = new TemporaryFolder();


@Rule
public ExpectedException thrown = ExpectedException.none();

public AnalyzerMediumTester tester = AnalyzerMediumTester.builder() public AnalyzerMediumTester tester = AnalyzerMediumTester.builder()
.registerPlugin("xoo", new XooPlugin()) .registerPlugin("xoo", new XooPlugin())
.registerLanguage(new Xoo()) .registerLanguage(new Xoo())
assertThat(result.inputFiles()).hasSize(4); assertThat(result.inputFiles()).hasSize(4);
} }


@Test
public void failForDuplicateInputFile() throws IOException {
File srcDir = new File(baseDir, "src");
srcDir.mkdir();

File xooFile = new File(srcDir, "sample.xoo");
FileUtils.write(xooFile, "Sample xoo\ncontent");

thrown.expect(MessageException.class);
thrown.expectMessage("can't be indexed twice. Please check that inclusion/exclusion patterns produce disjoint sets for main and test files");
tester.newTask()
.properties(builder
.put("sonar.sources", "src,src/sample.xoo")
.build())
.start();

}

} }

Laden…
Abbrechen
Speichern