aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-06-24 09:44:40 +0200
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-06-24 14:34:21 +0200
commit3630f86f9aaa8edaf7b5ee84d1f858da5dd2b01b (patch)
tree94f33cdc095a75f68f558855a50abecbc60f3b89
parentc4f18158c668a4640dac2d2e9fac15b9c3d1005e (diff)
downloadsonarqube-3630f86f9aaa8edaf7b5ee84d1f858da5dd2b01b.tar.gz
sonarqube-3630f86f9aaa8edaf7b5ee84d1f858da5dd2b01b.zip
Fix lock on windows
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempFolderProvider.java17
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempFolderProviderTest.java31
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java58
-rw-r--r--sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java2
4 files changed, 87 insertions, 21 deletions
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 b1ee968f344..175009bd898 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,6 +19,8 @@
*/
package org.sonar.batch.bootstrap;
+import org.sonar.api.utils.System2;
+
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.apache.commons.io.FileUtils;
@@ -40,7 +42,16 @@ public class TempFolderProvider extends LifecycleProviderAdapter {
private static final long CLEAN_MAX_AGE = TimeUnit.DAYS.toMillis(21);
static final String TMP_NAME_PREFIX = ".sonartmp_";
+ private System2 system;
private DefaultTempFolder tempFolder;
+
+ public TempFolderProvider() {
+ this(new System2());
+ }
+
+ TempFolderProvider(System2 system) {
+ this.system = system;
+ }
public TempFolder provide(BootstrapProperties bootstrapProps) {
if (tempFolder == null) {
@@ -71,19 +82,19 @@ public class TempFolderProvider extends LifecycleProviderAdapter {
return tempFolder;
}
- private static Path findHome(BootstrapProperties props) {
+ private Path findHome(BootstrapProperties props) {
String home = props.property("sonar.userHome");
if (home != null) {
return Paths.get(home);
}
- home = System.getenv("SONAR_USER_HOME");
+ home = system.envVariable("SONAR_USER_HOME");
if (home != null) {
return Paths.get(home);
}
- home = System.getProperty("user.home");
+ home = system.property("user.home");
return Paths.get(home, ".sonar");
}
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 8c1e23b7b56..3192641f791 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,6 +19,7 @@
*/
package org.sonar.batch.bootstrap;
+import org.sonar.api.utils.System2;
import org.apache.commons.io.FileUtils;
import org.sonar.api.utils.TempFolder;
import com.google.common.collect.ImmutableMap;
@@ -32,6 +33,8 @@ import java.nio.file.attribute.FileTime;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Rule;
import org.junit.Test;
@@ -45,19 +48,21 @@ public class TempFolderProviderTest {
@Test
public void createTempFolderProps() throws Exception {
- File workingDir = temp.getRoot();
+ File workingDir = temp.newFolder();
TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of(CoreProperties.GLOBAL_WORKING_DIRECTORY, workingDir.getAbsolutePath())));
tempFolder.newDir();
tempFolder.newFile();
assertThat(getCreatedTempDir(workingDir)).exists();
assertThat(getCreatedTempDir(workingDir).list()).hasSize(2);
+
+ FileUtils.deleteQuietly(workingDir);
}
@Test
public void cleanUpOld() throws IOException {
long creationTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(100);
- File workingDir = temp.getRoot();
+ File workingDir = temp.newFolder();
for (int i = 0; i < 3; i++) {
File tmp = new File(workingDir, ".sonartmp_" + i);
@@ -68,30 +73,37 @@ public class TempFolderProviderTest {
tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of(CoreProperties.GLOBAL_WORKING_DIRECTORY, workingDir.getAbsolutePath())));
// this also checks that all other temps were deleted
assertThat(getCreatedTempDir(workingDir)).exists();
+
+ FileUtils.deleteQuietly(workingDir);
}
@Test
public void createTempFolderSonarHome() throws Exception {
// with sonar home, it will be in {sonar.home}/.sonartmp
- File sonarHome = temp.getRoot();
- File workingDir = new File(sonarHome, CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE);
+ File sonarHome = temp.newFolder();
+ File workingDir = new File(sonarHome, CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE).getAbsoluteFile();
TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(ImmutableMap.of("sonar.userHome", sonarHome.getAbsolutePath())));
tempFolder.newDir();
tempFolder.newFile();
assertThat(getCreatedTempDir(workingDir)).exists();
assertThat(getCreatedTempDir(workingDir).list()).hasSize(2);
+
+ FileUtils.deleteQuietly(sonarHome);
}
@Test
public void createTempFolderDefault() throws Exception {
- File userHome = temp.getRoot();
- System.setProperty("user.home", userHome.getAbsolutePath());
+ System2 system = mock(System2.class);
+ tempFolderProvider = new TempFolderProvider(system);
+ File userHome = temp.newFolder();
+
+ when(system.envVariable("SONAR_USER_HOME")).thenReturn(null);
+ when(system.property("user.home")).thenReturn(userHome.getAbsolutePath().toString());
// if nothing is defined, it will be in {user.home}/.sonar/.sonartmp
- File defaultSonarHome = new File(System.getProperty("user.home"), ".sonar");
+ File defaultSonarHome = new File(userHome.getAbsolutePath(), ".sonar");
File workingDir = new File(defaultSonarHome, CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE).getAbsoluteFile();
-
try {
TempFolder tempFolder = tempFolderProvider.provide(new BootstrapProperties(Collections.<String, String>emptyMap()));
tempFolder.newDir();
@@ -99,11 +111,12 @@ public class TempFolderProviderTest {
assertThat(getCreatedTempDir(workingDir)).exists();
assertThat(getCreatedTempDir(workingDir).list()).hasSize(2);
} finally {
- FileUtils.deleteDirectory(getCreatedTempDir(workingDir));
+ FileUtils.deleteQuietly(workingDir);
}
}
private File getCreatedTempDir(File workingDir) {
+ assertThat(workingDir).isDirectory();
assertThat(workingDir.listFiles()).hasSize(1);
return workingDir.listFiles()[0];
}
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
index 3ceeaa47f3d..6af55ef6271 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
+import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
@@ -34,7 +35,6 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -60,7 +60,7 @@ public class PersistentCache {
this.log = log;
reconfigure(forceUpdate);
- log.info("cache: " + baseDir + ", default expiration time (ms): " + defaultDurationToExpireMs);
+ log.debug("cache: " + baseDir + ", default expiration time (ms): " + defaultDurationToExpireMs);
}
public void reconfigure(boolean forceUpdate) {
@@ -109,7 +109,8 @@ public class PersistentCache {
public synchronized byte[] get(@Nonnull String obj, @Nullable Callable<byte[]> valueLoader) throws Exception {
String key = getKey(obj);
- try (FileLock l = lock()) {
+ try {
+ lock();
if (!forceUpdate) {
byte[] cached = getCache(key);
@@ -130,6 +131,8 @@ public class PersistentCache {
}
return value;
}
+ } finally {
+ unlock();
}
return null;
@@ -140,10 +143,13 @@ public class PersistentCache {
*/
public synchronized void clear() {
log.info("cache: clearing");
- try (FileLock l = lock()) {
+ try {
+ lock();
deleteCacheEntries(createClearFilter());
} catch (IOException e) {
log.error("Error clearing cache", e);
+ } finally {
+ unlock();
}
}
@@ -152,16 +158,52 @@ public class PersistentCache {
*/
public synchronized void clean() {
log.info("cache: cleaning");
- try (FileLock l = lock()) {
+ try {
+ lock();
deleteCacheEntries(createCleanFilter());
} catch (IOException e) {
log.error("Error cleaning cache", e);
+ } finally {
+ unlock();
}
}
- private FileLock lock() throws IOException {
- FileChannel ch = FileChannel.open(getLockPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
- return ch.lock();
+ private void lock() throws IOException {
+ lock_raf = new RandomAccessFile(getLockPath().toFile(), "rw");
+ lock_fc = lock_raf.getChannel();
+ lock = lock_fc.lock();
+ }
+
+ private RandomAccessFile lock_raf;
+ private FileChannel lock_fc;
+ private FileLock lock;
+
+ private void unlock() {
+ if (lock != null) {
+ try {
+ lock.release();
+ } catch (IOException e) {
+ log.error("Error releasing lock", e);
+ }
+ }
+ if (lock_fc != null) {
+ try {
+ lock_fc.close();
+ } catch (IOException e) {
+ log.error("Error closing file channel", e);
+ }
+ }
+ if (lock_raf != null) {
+ try {
+ lock_raf.close();
+ } catch (IOException e) {
+ log.error("Error closing file", e);
+ }
+ }
+
+ lock = null;
+ lock_raf = null;
+ lock_fc = null;
}
private String getKey(String uri) {
diff --git a/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java b/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
index 8f8596e0705..e9abb0bc609 100644
--- a/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
+++ b/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
@@ -103,7 +103,7 @@ public class PersistentCacheTest {
assertCacheHit(false);
File root = tmp.getRoot();
- FileUtils.deleteDirectory(root);
+ FileUtils.deleteQuietly(root);
// should re-create cache directory and start using the cache
cache.reconfigure(false);