From: Duarte Meneses Date: Fri, 12 Jun 2015 08:40:59 +0000 (+0200) Subject: SONAR-6649 Move initialization of persistit cache to global context X-Git-Tag: 5.2-RC1~1342 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=12a57c668bb33f808cdae781a8d9308283c3da05;p=sonarqube.git SONAR-6649 Move initialization of persistit cache to global context --- diff --git a/pom.xml b/pom.xml index eecb91688d7..eae7b1b6c72 100644 --- a/pom.xml +++ b/pom.xml @@ -1093,7 +1093,7 @@ org.codehaus.sonar sonar-persistit - 3.3.1 + 3.3.2-SNAPSHOT commons-logging diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/TempFolderProvider.java b/server/sonar-server/src/main/java/org/sonar/server/platform/TempFolderProvider.java index 2d2f598db80..6c21893338c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/TempFolderProvider.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/TempFolderProvider.java @@ -44,5 +44,4 @@ public class TempFolderProvider extends ProviderAdapter { } return tempFolder; } - } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java index 32e6aa6ce81..08d9cbb9a7c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java @@ -19,8 +19,11 @@ */ package org.sonar.batch.bootstrap; +import org.sonar.batch.index.CachesManager; + import java.util.List; import java.util.Map; + import org.sonar.api.CoreProperties; import org.sonar.api.Plugin; import org.sonar.api.utils.Durations; @@ -98,6 +101,7 @@ public class GlobalContainer extends ComponentContainer { BatchPluginPredicate.class, ExtensionInstaller.class, + CachesManager.class, GlobalSettings.class, ServerClient.class, Logback.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectTempFolderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectTempFolderProvider.java new file mode 100644 index 00000000000..e83013371ad --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectTempFolderProvider.java @@ -0,0 +1,52 @@ +/* + * 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.batch.bootstrap; + +import org.sonar.api.utils.ProjectTempFolder; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.api.CoreProperties; +import org.sonar.api.utils.internal.DefaultTempFolder; + +import java.io.File; +import java.io.IOException; + +public class ProjectTempFolderProvider extends ProviderAdapter { + static final String TMP_NAME = ".sonartmp"; + private ProjectTempFolder projectTempFolder; + + public ProjectTempFolder provide(BootstrapProperties bootstrapProps) { + if (projectTempFolder == null) { + String workingDirPath = StringUtils.defaultIfBlank(bootstrapProps.property(CoreProperties.WORKING_DIRECTORY), CoreProperties.WORKING_DIRECTORY_DEFAULT_VALUE); + File workingDir = new File(workingDirPath).getAbsoluteFile(); + File tempDir = new File(workingDir, TMP_NAME); + try { + FileUtils.forceMkdir(tempDir); + } catch (IOException e) { + throw new IllegalStateException("Unable to create root temp directory " + tempDir, e); + } + projectTempFolder = new DefaultTempFolder(tempDir, true); + } + return projectTempFolder; + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempFolderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempFolderProvider.java index b665d9d3279..971a4a2b1f5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempFolderProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempFolderProvider.java @@ -19,33 +19,57 @@ */ package org.sonar.batch.bootstrap; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.TempFolder; import org.picocontainer.injectors.ProviderAdapter; +import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.utils.TempFolder; import org.sonar.api.utils.internal.DefaultTempFolder; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class TempFolderProvider extends ProviderAdapter { - + static final String TMP_NAME = ".sonartmp"; private TempFolder tempFolder; public TempFolder provide(BootstrapProperties bootstrapProps) { if (tempFolder == null) { - String workingDirPath = StringUtils.defaultIfBlank(bootstrapProps.property(CoreProperties.WORKING_DIRECTORY), CoreProperties.WORKING_DIRECTORY_DEFAULT_VALUE); - File workingDir = new File(workingDirPath).getAbsoluteFile(); - File tempDir = new File(workingDir, ".sonartmp"); + + String workingPathName = StringUtils.defaultIfBlank(bootstrapProps.property(CoreProperties.GLOBAL_WORKING_DIRECTORY), CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE); + Path workingPath = Paths.get(workingPathName).normalize(); + + if (!workingPath.isAbsolute()) { + Path home = findHome(bootstrapProps); + workingPath = home.resolve(workingPath).normalize(); + } + + Path tempDir = workingPath.resolve(TMP_NAME); try { - FileUtils.forceMkdir(tempDir); + Files.createDirectories(tempDir); } catch (IOException e) { throw new IllegalStateException("Unable to create root temp directory " + tempDir, e); } - tempFolder = new DefaultTempFolder(tempDir); + tempFolder = new DefaultTempFolder(tempDir.toFile(), true); } return tempFolder; } + private static Path findHome(BootstrapProperties props) { + String home = props.property("sonar.userHome"); + if (home != null) { + return Paths.get(home); + } + + home = System.getenv("SONAR_USER_HOME"); + + if (home != null) { + return Paths.get(home); + } + + home = System.getProperty("user.home"); + return Paths.get(home, ".sonar"); + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java index 3d1250eeba6..da83b54becb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java @@ -27,6 +27,7 @@ import org.sonar.core.config.Logback; import javax.annotation.Nullable; import java.io.File; +import java.io.PrintStream; import java.util.Map; /** @@ -72,6 +73,11 @@ public final class LoggingConfiguration { setVerbose(verbose); return this; } + + public LoggingConfiguration setStreams(PrintStream out, PrintStream err) { + + return this; + } public LoggingConfiguration setVerbose(boolean verbose) { return setRootLevel(verbose ? LEVEL_ROOT_VERBOSE : LEVEL_ROOT_DEFAULT); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java index bc6314d7475..209ec7792aa 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java @@ -19,64 +19,40 @@ */ package org.sonar.batch.index; +import com.google.common.collect.Maps; + +import java.util.Map; +import java.util.Map.Entry; + import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; import com.persistit.Exchange; -import com.persistit.Persistit; import com.persistit.Value; -import com.persistit.Volume; import com.persistit.encoding.CoderManager; +import com.persistit.Persistit; import com.persistit.encoding.ValueCoder; import com.persistit.exception.PersistitException; -import com.persistit.logging.Slf4jAdapter; -import org.apache.commons.io.FileUtils; +import com.persistit.Volume; import org.picocontainer.Startable; -import org.slf4j.LoggerFactory; import org.sonar.api.batch.BatchSide; -import org.sonar.api.utils.TempFolder; -import java.io.File; -import java.util.Properties; -import java.util.Set; - -/** - * Factory of caches - * - * @since 3.6 - */ @BatchSide public class Caches implements Startable { - - private final Set cacheNames = Sets.newHashSet(); - private File tempDir; + private final Map caches = Maps.newHashMap(); private Persistit persistit; private Volume volume; - private final TempFolder tempFolder; - public Caches(TempFolder tempFolder) { - this.tempFolder = tempFolder; - initPersistit(); + public Caches(CachesManager caches) { + persistit = caches.persistit(); + start(); } - private void initPersistit() { + @Override + public void start() { try { - tempDir = tempFolder.newDir("caches"); - persistit = new Persistit(); - persistit.setPersistitLogger(new Slf4jAdapter(LoggerFactory.getLogger("PERSISTIT"))); - Properties props = new Properties(); - props.setProperty("datapath", tempDir.getAbsolutePath()); - props.setProperty("logpath", "${datapath}/log"); - props.setProperty("logfile", "${logpath}/persistit_${timestamp}.log"); - props.setProperty("buffer.count.8192", "10"); - props.setProperty("journalpath", "${datapath}/journal"); - props.setProperty("tmpvoldir", "${datapath}"); - props.setProperty("volume.1", "${datapath}/persistit,create,pageSize:8192,initialPages:10,extensionPages:100,maximumPages:25000"); - persistit.setProperties(props); - persistit.initialize(); + persistit.flush(); volume = persistit.createTemporaryVolume(); - } catch (Exception e) { - throw new IllegalStateException("Fail to start caches", e); + throw new IllegalStateException("Fail to create a cache volume", e); } } @@ -87,44 +63,34 @@ public class Caches implements Startable { public Cache createCache(String cacheName) { Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized"); - Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName); + Preconditions.checkState(!caches.containsKey(cacheName), "Cache is already created: " + cacheName); try { Exchange exchange = persistit.getExchange(volume, cacheName, true); exchange.setMaximumValueSize(Value.MAXIMUM_SIZE); Cache cache = new Cache<>(cacheName, exchange); - cacheNames.add(cacheName); + caches.put(cacheName, exchange); return cache; } catch (Exception e) { throw new IllegalStateException("Fail to create cache: " + cacheName, e); } } - @Override - public void start() { - // already started in constructor - } - @Override public void stop() { - if (persistit != null) { + for (Entry e : caches.entrySet()) { + persistit.releaseExchange(e.getValue()); + } + + caches.clear(); + + if (volume != null) { try { - persistit.close(false); - persistit = null; - volume = null; + volume.close(); + volume.delete(); } catch (PersistitException e) { throw new IllegalStateException("Fail to close caches", e); } + volume = null; } - FileUtils.deleteQuietly(tempDir); - tempDir = null; - cacheNames.clear(); - } - - File tempDir() { - return tempDir; - } - - Persistit persistit() { - return persistit; } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/CachesManager.java b/sonar-batch/src/main/java/org/sonar/batch/index/CachesManager.java new file mode 100644 index 00000000000..107c62a619c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/index/CachesManager.java @@ -0,0 +1,98 @@ +/* + * 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.batch.index; + +import org.sonar.api.utils.TempFolder; + +import com.persistit.Persistit; +import com.persistit.exception.PersistitException; +import com.persistit.logging.Slf4jAdapter; +import org.apache.commons.io.FileUtils; +import org.picocontainer.Startable; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.BatchSide; + +import java.io.File; +import java.util.Properties; + +/** + * Factory of caches + * + * @since 3.6 + */ +@BatchSide +public class CachesManager implements Startable { + private File tempDir; + private Persistit persistit; + private final TempFolder tempFolder; + + public CachesManager(TempFolder tempFolder) { + this.tempFolder = tempFolder; + initPersistit(); + } + + private void initPersistit() { + try { + tempDir = tempFolder.newDir("caches"); + persistit = new Persistit(); + persistit.setPersistitLogger(new Slf4jAdapter(LoggerFactory.getLogger("PERSISTIT"))); + Properties props = new Properties(); + props.setProperty("datapath", tempDir.getAbsolutePath()); + props.setProperty("logpath", "${datapath}/log"); + props.setProperty("logfile", "${logpath}/persistit_${timestamp}.log"); + props.setProperty("buffer.count.8192", "10"); + props.setProperty("journalpath", "${datapath}/journal"); + props.setProperty("tmpvoldir", "${datapath}"); + props.setProperty("volume.1", "${datapath}/persistit,create,pageSize:8192,initialPages:10,extensionPages:100,maximumPages:25000"); + persistit.setProperties(props); + persistit.initialize(); + + } catch (Exception e) { + throw new IllegalStateException("Fail to start caches", e); + } + } + + @Override + public void start() { + // already started in constructor + } + + @Override + public void stop() { + if (persistit != null) { + try { + persistit.close(false); + persistit = null; + } catch (PersistitException e) { + throw new IllegalStateException("Fail to close caches", e); + } + } + FileUtils.deleteQuietly(tempDir); + tempDir = null; + } + + File tempDir() { + return tempDir; + } + + Persistit persistit() { + return persistit; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 59eae4f9303..623fd0fa90e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -19,6 +19,10 @@ */ package org.sonar.batch.scan; +import org.sonar.batch.bootstrap.ProjectTempFolderProvider; + +import org.sonar.api.utils.internal.TempFolderCleaner; +import org.sonar.batch.bootstrap.TempFolderProvider; import com.google.common.annotations.VisibleForTesting; import org.sonar.api.CoreProperties; import org.sonar.api.batch.InstantiationStrategy; @@ -151,7 +155,10 @@ public class ProjectScanContainer extends ComponentContainer { Caches.class, BatchComponentCache.class, - // file system + //temp + new ProjectTempFolderProvider(), + + // file system InputPathCache.class, PathResolver.class, diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectTempFolderProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectTempFolderProviderTest.java new file mode 100644 index 00000000000..e79f0516159 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectTempFolderProviderTest.java @@ -0,0 +1,70 @@ +/* + * 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.batch.bootstrap; + +import org.apache.commons.io.FileUtils; + +import org.sonar.api.utils.ProjectTempFolder; +import com.google.common.collect.ImmutableMap; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProjectTempFolderProviderTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private ProjectTempFolderProvider tempFolderProvider = new ProjectTempFolderProvider(); + + @Test + public void createTempFolderWithProps() throws Exception { + File workingDir = temp.newFolder(); + File tmpDir = new File(workingDir, ProjectTempFolderProvider.TMP_NAME); + + ProjectTempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, workingDir.getAbsolutePath()))); + tempFolder.newDir(); + tempFolder.newFile(); + assertThat(tmpDir).exists(); + assertThat(tmpDir.list()).hasSize(2); + } + + @Test + public void createTempFolder() throws IOException { + File defaultDir = new File(CoreProperties.WORKING_DIRECTORY_DEFAULT_VALUE, ProjectTempFolderProvider.TMP_NAME); + + try { + ProjectTempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(Collections.emptyMap())); + tempFolder.newDir(); + tempFolder.newFile(); + assertThat(defaultDir).exists(); + assertThat(defaultDir.list()).hasSize(2); + } finally { + FileUtils.deleteDirectory(defaultDir); + } + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempFolderProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempFolderProviderTest.java index 9db9e6d1013..ce64074d9a6 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempFolderProviderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempFolderProviderTest.java @@ -19,34 +19,63 @@ */ package org.sonar.batch.bootstrap; +import org.apache.commons.io.FileUtils; +import org.sonar.api.utils.TempFolder; import com.google.common.collect.ImmutableMap; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; import org.sonar.api.CoreProperties; -import org.sonar.api.utils.TempFolder; import java.io.File; +import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; public class TempFolderProviderTest { - - @Rule - public ExpectedException throwable = ExpectedException.none(); - @Rule public TemporaryFolder temp = new TemporaryFolder(); + private TempFolderProvider tempFolderProvider = new TempFolderProvider(); + @Test - public void createTempFolder() throws Exception { + public void createTempFolderProps() throws Exception { File workingDir = temp.newFolder(); - TempFolderProvider tempFolderProvider = new TempFolderProvider(); - TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, workingDir.getAbsolutePath()))); + + TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of(CoreProperties.GLOBAL_WORKING_DIRECTORY, workingDir.getAbsolutePath()))); tempFolder.newDir(); tempFolder.newFile(); - assertThat(new File(workingDir, ".sonartmp")).exists(); + assertThat(new File(workingDir, TempFolderProvider.TMP_NAME)).exists(); assertThat(new File(workingDir, ".sonartmp").list()).hasSize(2); } + + @Test + public void createTempFolderSonarHome() throws Exception { + // with sonar home, it will be in {sonar.home}/.sonartmp + File sonarHome = temp.newFolder(); + File tmpDir = new File(new File(sonarHome, CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE), TempFolderProvider.TMP_NAME); + + TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of("sonar.userHome", sonarHome.getAbsolutePath()))); + tempFolder.newDir(); + tempFolder.newFile(); + assertThat(tmpDir).exists(); + assertThat(tmpDir.list()).hasSize(2); + } + + @Test + public void createTempFolderDefault() throws Exception { + // if nothing is defined, it will be in {user.home}/.sonar/.sonartmp + File defaultSonarHome = new File(System.getProperty("user.home"), ".sonar"); + File tmpDir = new File(new File(defaultSonarHome, CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE), TempFolderProvider.TMP_NAME); + + try { + TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(Collections.emptyMap())); + tempFolder.newDir(); + tempFolder.newFile(); + assertThat(tmpDir).exists(); + assertThat(tmpDir.list()).hasSize(2); + } finally { + FileUtils.deleteDirectory(tmpDir); + } + } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java index 14254a9d9f6..f5913814740 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java @@ -19,40 +19,20 @@ */ package org.sonar.batch.duplication; -import org.junit.After; -import org.junit.Before; +import org.sonar.batch.index.AbstractCachesTest; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.sensor.duplication.Duplication; import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import org.sonar.batch.index.Caches; -import org.sonar.batch.index.CachesTest; - import static org.assertj.core.api.Assertions.assertThat; -public class DuplicationCacheTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); +public class DuplicationCacheTest extends AbstractCachesTest { @Rule public ExpectedException thrown = ExpectedException.none(); - Caches caches; - - @Before - public void start() { - caches = CachesTest.createCacheOnTemp(temp); - caches.start(); - } - - @After - public void stop() { - caches.stop(); - } - @Test public void should_add_clone_groups() { DuplicationCache cache = new DuplicationCache(caches); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/AbstractCachesTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/AbstractCachesTest.java new file mode 100644 index 00000000000..08116780821 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/index/AbstractCachesTest.java @@ -0,0 +1,59 @@ +/* + * 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.batch.index; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.rules.TemporaryFolder; + +public abstract class AbstractCachesTest { + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + protected Caches caches; + protected static CachesManager cachesManager; + + @BeforeClass + public static void startClass() { + cachesManager = CachesManagerTest.createCacheOnTemp(temp); + cachesManager.start(); + } + + @Before + public void start() { + caches = new Caches(cachesManager); + caches.start(); + } + + @After + public void stop() { + caches.stop(); + caches = null; + } + + @AfterClass + public static void stopClass() { + cachesManager.stop(); + cachesManager = null; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java index 9c85d02c0fd..64aaf4f0ad2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java @@ -20,32 +20,12 @@ package org.sonar.batch.index; import com.google.common.collect.Iterables; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.sonar.batch.index.Cache.Entry; import static org.assertj.core.api.Assertions.assertThat; -public class CacheTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - Caches caches; - - @Before - public void start() { - caches = CachesTest.createCacheOnTemp(temp); - caches.start(); - } - - @After - public void stop() { - caches.stop(); - } +public class CacheTest extends AbstractCachesTest { @Test public void one_part_key() { diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CachesManagerTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CachesManagerTest.java new file mode 100644 index 00000000000..6d301a7ec4d --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CachesManagerTest.java @@ -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.batch.index; + +import org.sonar.batch.bootstrap.TempFolderProvider; + +import com.google.common.collect.ImmutableMap; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.batch.bootstrap.BootstrapProperties; + +import java.io.File; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CachesManagerTest { + + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + public static CachesManager createCacheOnTemp(TemporaryFolder temp) { + try { + BootstrapProperties bootstrapProps = new BootstrapProperties(ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, temp.newFolder().getAbsolutePath())); + return new CachesManager(new TempFolderProvider().provide(bootstrapProps)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + CachesManager cachesMgr; + + @Before + public void prepare() { + cachesMgr = createCacheOnTemp(temp); + cachesMgr.start(); + } + + @Test + public void should_stop_and_clean_temp_dir() { + File tempDir = cachesMgr.tempDir(); + assertThat(tempDir).isDirectory().exists(); + assertThat(cachesMgr.persistit()).isNotNull(); + assertThat(cachesMgr.persistit().isInitialized()).isTrue(); + + cachesMgr.stop(); + + assertThat(tempDir).doesNotExist(); + assertThat(cachesMgr.tempDir()).isNull(); + assertThat(cachesMgr.persistit()).isNull(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java index 83e2a99b948..801d0f3d5ed 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java @@ -19,73 +19,22 @@ */ package org.sonar.batch.index; -import com.google.common.collect.ImmutableMap; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.batch.bootstrap.BootstrapProperties; -import org.sonar.batch.bootstrap.TempFolderProvider; - -import java.io.File; -import java.io.IOException; import java.io.Serializable; +import com.persistit.exception.PersistitException; +import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; -public class CachesTest { - - @ClassRule - public static TemporaryFolder temp = new TemporaryFolder(); - - public static Caches createCacheOnTemp(TemporaryFolder temp) { - try { - BootstrapProperties bootstrapProps = new BootstrapProperties(ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, temp.newFolder().getAbsolutePath())); - return new Caches(new TempFolderProvider().provide(bootstrapProps)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - Caches caches; - - @Before - public void prepare() { - caches = createCacheOnTemp(temp); - } - - @After - public void stop() { - caches.stop(); - } - - @Test - public void should_stop_and_clean_temp_dir() { - File tempDir = caches.tempDir(); - assertThat(tempDir).isDirectory().exists(); - assertThat(caches.persistit()).isNotNull(); - assertThat(caches.persistit().isInitialized()).isTrue(); - - caches.stop(); - - assertThat(tempDir).doesNotExist(); - assertThat(caches.tempDir()).isNull(); - assertThat(caches.persistit()).isNull(); - } - +public class CachesTest extends AbstractCachesTest { @Test public void should_create_cache() { - caches.start(); Cache cache = caches.createCache("foo"); assertThat(cache).isNotNull(); } @Test public void should_not_create_cache_twice() { - caches.start(); caches.createCache("foo"); try { caches.createCache("foo"); @@ -95,7 +44,48 @@ public class CachesTest { } } - static class Element implements Serializable { + @Test + public void should_clean_resources() throws PersistitException { + Cache c = caches.createCache("test1"); + for (int i = 0; i < 1_000_000; i++) { + c.put("a" + i, "a" + i); + } + + caches.stop(); + + // manager continues up + assertThat(cachesManager.persistit().isInitialized()).isTrue(); + + caches = new Caches(cachesManager); + caches.start(); + caches.createCache("test1"); + } + + @Test + public void leak_test() throws PersistitException { + caches.stop(); + + System.out.println(cachesManager.tempDir()); + + int len = 1 * 1024 * 1024; + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + sb.append("a"); + } + + for (int i = 0; i < 3; i++) { + caches = new Caches(cachesManager); + caches.start(); + Cache c = caches.createCache("test" + i); + c.put("key" + i, sb.toString()); + cachesManager.persistit().flush(); + + caches.stop(); + } + } + + private static class Element implements Serializable { + private static final long serialVersionUID = 1L; } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java index 46e297f2e4e..25fefe6f13d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java @@ -19,19 +19,15 @@ */ package org.sonar.batch.issue; +import org.sonar.batch.index.AbstractCachesTest; + import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rule.Severity; -import org.sonar.batch.index.Caches; -import org.sonar.batch.index.CachesTest; import javax.annotation.Nullable; @@ -41,23 +37,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class IssueCacheTest { - - @ClassRule - public static TemporaryFolder temp = new TemporaryFolder(); - - Caches caches; - - @Before - public void start() { - caches = CachesTest.createCacheOnTemp(temp); - caches.start(); - } - - @After - public void stop() { - caches.stop(); - } +public class IssueCacheTest extends AbstractCachesTest { @Test public void should_add_new_issue() { diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java index 046f37840f9..c6f42f12b6a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java @@ -20,46 +20,24 @@ package org.sonar.batch.issue.tracking; +import org.sonar.batch.index.AbstractCachesTest; + import org.junit.After; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.batch.bootstrap.BootstrapProperties; -import org.sonar.batch.bootstrap.TempFolderProvider; -import org.sonar.batch.index.Caches; import org.sonar.core.issue.db.IssueChangeDto; import org.sonar.core.issue.db.IssueDto; -import java.io.IOException; -import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class InitialOpenIssuesStackTest { - - @ClassRule - public static TemporaryFolder temp = new TemporaryFolder(); - - public static Caches createCacheOnTemp(TemporaryFolder temp) { - BootstrapProperties bootstrapSettings = new BootstrapProperties(Collections.emptyMap()); - try { - bootstrapSettings.properties().put(CoreProperties.WORKING_DIRECTORY, temp.newFolder().getAbsolutePath()); - } catch (IOException e) { - throw new RuntimeException(e); - } - return new Caches(new TempFolderProvider().provide(bootstrapSettings)); - } +public class InitialOpenIssuesStackTest extends AbstractCachesTest { InitialOpenIssuesStack stack; - Caches caches; @Before public void before() { - caches = createCacheOnTemp(temp); - caches.start(); stack = new InitialOpenIssuesStack(caches); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java index 598f2a5ce2e..0575a850182 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java @@ -19,13 +19,12 @@ */ package org.sonar.batch.scan.measure; +import org.sonar.batch.index.AbstractCachesTest; import org.apache.commons.lang.builder.EqualsBuilder; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; @@ -42,8 +41,6 @@ import org.sonar.api.technicaldebt.batch.Requirement; import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; import org.sonar.batch.index.Cache.Entry; -import org.sonar.batch.index.Caches; -import org.sonar.batch.index.CachesTest; import java.util.Date; import java.util.Iterator; @@ -52,101 +49,90 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class MeasureCacheTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - +public class MeasureCacheTest extends AbstractCachesTest { @Rule public ExpectedException thrown = ExpectedException.none(); - Caches caches; - private MetricFinder metricFinder; private TechnicalDebtModel techDebtModel; - private MeasureCache cache; + private MeasureCache measureCache; @Before public void start() { - caches = CachesTest.createCacheOnTemp(temp); - caches.start(); + super.start(); metricFinder = mock(MetricFinder.class); when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC); techDebtModel = mock(TechnicalDebtModel.class); - cache = new MeasureCache(caches, metricFinder, techDebtModel); - } - - @After - public void stop() { - caches.stop(); + measureCache = new MeasureCache(caches, metricFinder, techDebtModel); } @Test public void should_add_measure() { Project p = new Project("struts"); - assertThat(cache.entries()).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); Measure m = new Measure(CoreMetrics.NCLOC, 1.0); - cache.put(p, m); + measureCache.put(p, m); - assertThat(cache.contains(p, m)).isTrue(); - assertThat(cache.entries()).hasSize(1); - Iterator> iterator = cache.entries().iterator(); + assertThat(measureCache.contains(p, m)).isTrue(); + assertThat(measureCache.entries()).hasSize(1); + Iterator> iterator = measureCache.entries().iterator(); iterator.hasNext(); Entry next = iterator.next(); assertThat(next.value()).isEqualTo(m); assertThat(next.key()[0]).isEqualTo("struts"); - assertThat(cache.byResource(p)).hasSize(1); - assertThat(cache.byResource(p).iterator().next()).isEqualTo(m); + assertThat(measureCache.byResource(p)).hasSize(1); + assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); Measure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); - cache.put(p, mRule); + measureCache.put(p, mRule); - assertThat(cache.entries()).hasSize(2); + assertThat(measureCache.entries()).hasSize(2); - assertThat(cache.byResource(p)).hasSize(2); + assertThat(measureCache.byResource(p)).hasSize(2); } @Test - public void should_add_measure_with_big_data() { + public void should_add_measure_with_big_data() throws InterruptedException { Project p = new Project("struts"); - assertThat(cache.entries()).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date()); m.setAlertText("foooooooooooooooooooooooooooooooooooo"); StringBuilder data = new StringBuilder(); - for (int i = 0; i < 1048575; i++) { + for (int i = 0; i < 1_048_575; i++) { data.append("a"); } + m.setData(data.toString()); - cache.put(p, m); + measureCache.put(p, m); - assertThat(cache.contains(p, m)).isTrue(); - assertThat(cache.entries()).hasSize(1); - Iterator> iterator = cache.entries().iterator(); + assertThat(measureCache.contains(p, m)).isTrue(); + assertThat(measureCache.entries()).hasSize(1); + Iterator> iterator = measureCache.entries().iterator(); iterator.hasNext(); Entry next = iterator.next(); assertThat(next.value()).isEqualTo(m); assertThat(next.key()[0]).isEqualTo("struts"); - assertThat(cache.byResource(p)).hasSize(1); - assertThat(cache.byResource(p).iterator().next()).isEqualTo(m); + assertThat(measureCache.byResource(p)).hasSize(1); + assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); mRule.setRuleKey(RuleKey.of("repo", "rule")); - cache.put(p, mRule); + measureCache.put(p, mRule); - assertThat(cache.entries()).hasSize(2); + assertThat(measureCache.entries()).hasSize(2); } /** @@ -156,9 +142,9 @@ public class MeasureCacheTest { public void should_add_measure_with_too_big_data_for_persistit_pre_patch() { Project p = new Project("struts"); - assertThat(cache.entries()).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date()); StringBuilder data = new StringBuilder(); @@ -167,33 +153,33 @@ public class MeasureCacheTest { } m.setData(data.toString()); - cache.put(p, m); + measureCache.put(p, m); - assertThat(cache.contains(p, m)).isTrue(); - assertThat(cache.entries()).hasSize(1); - Iterator> iterator = cache.entries().iterator(); + assertThat(measureCache.contains(p, m)).isTrue(); + assertThat(measureCache.entries()).hasSize(1); + Iterator> iterator = measureCache.entries().iterator(); iterator.hasNext(); Entry next = iterator.next(); assertThat(next.value()).isEqualTo(m); assertThat(next.key()[0]).isEqualTo("struts"); - assertThat(cache.byResource(p)).hasSize(1); - assertThat(cache.byResource(p).iterator().next()).isEqualTo(m); + assertThat(measureCache.byResource(p)).hasSize(1); + assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); mRule.setRuleKey(RuleKey.of("repo", "rule")); - cache.put(p, mRule); + measureCache.put(p, mRule); - assertThat(cache.entries()).hasSize(2); + assertThat(measureCache.entries()).hasSize(2); } @Test public void should_add_measure_with_too_big_data_for_persistit() { Project p = new Project("struts"); - assertThat(cache.entries()).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date()); StringBuilder data = new StringBuilder(64 * 1024 * 1024 + 1); @@ -206,28 +192,28 @@ public class MeasureCacheTest { thrown.expect(IllegalStateException.class); thrown.expectMessage("Fail to put element in the cache measures"); - cache.put(p, m); + measureCache.put(p, m); } @Test public void should_add_measure_with_same_metric() { Project p = new Project("struts"); - assertThat(cache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); Measure m1 = new Measure(CoreMetrics.NCLOC, 1.0); Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setCharacteristic(new DefaultCharacteristic().setKey("charac")); Measure m3 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2); Measure m4 = new RuleMeasure(CoreMetrics.NCLOC, RuleKey.of("repo", "rule"), RulePriority.BLOCKER, null); - cache.put(p, m1); - cache.put(p, m2); - cache.put(p, m3); - cache.put(p, m4); + measureCache.put(p, m1); + measureCache.put(p, m2); + measureCache.put(p, m3); + measureCache.put(p, m4); - assertThat(cache.entries()).hasSize(4); + assertThat(measureCache.entries()).hasSize(4); - assertThat(cache.byResource(p)).hasSize(4); + assertThat(measureCache.byResource(p)).hasSize(4); } @Test @@ -237,36 +223,36 @@ public class MeasureCacheTest { Resource file1 = Directory.create("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt"); Resource file2 = Directory.create("foo/bar/File2.txt").setEffectiveKey("struts:foo/bar/File2.txt"); - assertThat(cache.entries()).hasSize(0); + assertThat(measureCache.entries()).hasSize(0); - assertThat(cache.byResource(p)).hasSize(0); - assertThat(cache.byResource(dir)).hasSize(0); + assertThat(measureCache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(dir)).hasSize(0); Measure mFile1 = new Measure(CoreMetrics.NCLOC, 1.0); - cache.put(file1, mFile1); + measureCache.put(file1, mFile1); Measure mFile2 = new Measure(CoreMetrics.NCLOC, 3.0); - cache.put(file2, mFile2); + measureCache.put(file2, mFile2); - assertThat(cache.entries()).hasSize(2); - assertThat(cache.byResource(p)).hasSize(0); - assertThat(cache.byResource(dir)).hasSize(0); + assertThat(measureCache.entries()).hasSize(2); + assertThat(measureCache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(dir)).hasSize(0); Measure mDir = new Measure(CoreMetrics.NCLOC, 4.0); - cache.put(dir, mDir); + measureCache.put(dir, mDir); - assertThat(cache.entries()).hasSize(3); - assertThat(cache.byResource(p)).hasSize(0); - assertThat(cache.byResource(dir)).hasSize(1); - assertThat(cache.byResource(dir).iterator().next()).isEqualTo(mDir); + assertThat(measureCache.entries()).hasSize(3); + assertThat(measureCache.byResource(p)).hasSize(0); + assertThat(measureCache.byResource(dir)).hasSize(1); + assertThat(measureCache.byResource(dir).iterator().next()).isEqualTo(mDir); Measure mProj = new Measure(CoreMetrics.NCLOC, 4.0); - cache.put(p, mProj); + measureCache.put(p, mProj); - assertThat(cache.entries()).hasSize(4); - assertThat(cache.byResource(p)).hasSize(1); - assertThat(cache.byResource(p).iterator().next()).isEqualTo(mProj); - assertThat(cache.byResource(dir)).hasSize(1); - assertThat(cache.byResource(dir).iterator().next()).isEqualTo(mDir); + assertThat(measureCache.entries()).hasSize(4); + assertThat(measureCache.byResource(p)).hasSize(1); + assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(mProj); + assertThat(measureCache.byResource(dir)).hasSize(1); + assertThat(measureCache.byResource(dir).iterator().next()).isEqualTo(mDir); } @Test @@ -274,9 +260,9 @@ public class MeasureCacheTest { Resource file1 = File.create("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt"); Measure measure = new Measure(CoreMetrics.NCLOC, 1.786, 5); - cache.put(file1, measure); + measureCache.put(file1, measure); - Measure savedMeasure = cache.byResource(file1).iterator().next(); + Measure savedMeasure = measureCache.byResource(file1).iterator().next(); assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); @@ -302,9 +288,9 @@ public class MeasureCacheTest { measure.setVariation3(13.0); measure.setVariation4(14.0); measure.setVariation5(15.0); - cache.put(file1, measure); + measureCache.put(file1, measure); - savedMeasure = cache.byResource(file1).iterator().next(); + savedMeasure = measureCache.byResource(file1).iterator().next(); assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index 4df29867109..88553184e82 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -467,7 +467,15 @@ public interface CoreProperties { * @since 4.0 */ String WORKING_DIRECTORY = "sonar.working.directory"; + String WORKING_DIRECTORY_DEFAULT_VALUE = ".sonar"; + + /** + * @since 5.2 + */ + String GLOBAL_WORKING_DIRECTORY = "sonar.globalWorking.directory"; + String GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE = "."; + /** * @since 3.4 diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/ProjectTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/ProjectTempFolder.java new file mode 100644 index 00000000000..276be831528 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/ProjectTempFolder.java @@ -0,0 +1,54 @@ +/* + * 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.api.utils; + +import javax.annotation.Nullable; + +import java.io.File; + +import org.sonar.api.batch.BatchSide; + + +/** + * Use this component to deal with temp files/folders that have a scope linked to each + * project analysis. + * Root location will typically be the working directory (see sonar.working.directory) + + * @since 5.2 + * + */ +@BatchSide +public interface ProjectTempFolder { + + /** + * Create a directory in temp folder with a random unique name. + */ + File newDir(); + + /** + * Create a directory in temp folder using provided name. + */ + File newDir(String name); + + File newFile(); + + File newFile(@Nullable String prefix, @Nullable String suffix); + +} \ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFolder.java index c456a020fc9..de63fadbfe4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFolder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFolder.java @@ -31,7 +31,7 @@ import java.io.File; * depends on situation: *
    *
  • ${SONAR_HOME}/temp on server side
  • - *
  • Working directory on batch side (see sonar.working.directory)
  • + *
  • ${SONAR_HOME}/.sonartmp on the batch side
  • *
* @since 4.0 * diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java index c96ecc3e488..86582192407 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java @@ -19,6 +19,7 @@ */ package org.sonar.api.utils.internal; +import org.sonar.api.utils.ProjectTempFolder; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.sonar.api.utils.TempFolder; @@ -29,15 +30,21 @@ import java.io.File; import java.io.IOException; import java.text.MessageFormat; -public class DefaultTempFolder implements TempFolder { +public class DefaultTempFolder implements TempFolder, ProjectTempFolder { /** Maximum loop count when creating temp directories. */ private static final int TEMP_DIR_ATTEMPTS = 10000; private final File tempDir; + private final boolean cleanUp; public DefaultTempFolder(File tempDir) { + this(tempDir, false); + } + + public DefaultTempFolder(File tempDir, boolean cleanUp) { this.tempDir = tempDir; + this.cleanUp = cleanUp; } @Override @@ -106,4 +113,10 @@ public class DefaultTempFolder implements TempFolder { FileUtils.deleteQuietly(tempDir); } + public void stop() { + if(cleanUp) { + clean(); + } + } + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java index 3a8c15bf474..e5cda14785f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java @@ -19,6 +19,8 @@ */ package org.sonar.api.utils.internal; +import org.sonar.api.utils.ProjectTempFolder; + import org.apache.commons.lang.StringUtils; import org.junit.rules.ExternalResource; import org.junit.rules.TemporaryFolder; @@ -51,7 +53,7 @@ import java.io.IOException; * * @since 5.1 */ -public class JUnitTempFolder extends ExternalResource implements TempFolder { +public class JUnitTempFolder extends ExternalResource implements TempFolder, ProjectTempFolder { private final TemporaryFolder junit = new TemporaryFolder();