WIP2 More tests on file lock

This commit is contained in:
dotasek 2024-09-10 17:07:27 -04:00
parent e001d781b9
commit f7cf74423c
3 changed files with 67 additions and 20 deletions

View File

@ -195,7 +195,7 @@ public class FilesystemPackageCacheManagerLocks {
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
FileLock fileLock = null;
while (fileLock == null) {
fileLock = channel.tryLock(0, Long.MAX_VALUE, true);
fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
if (fileLock == null) {
Thread.sleep(100); // Wait and retry
}

View File

@ -137,6 +137,24 @@ public class FilesystemPackageManagerTests {
assertThat(exception.getMessage()).contains("Lock file exists, but is not locked by a process");
}
private static Thread lockWaitAndDelete(String path, String lockFileName, int seconds) {
Thread t = new Thread(() -> {
ProcessBuilder processBuilder = new ProcessBuilder("java", "-cp", "target/test-classes:.", "org.hl7.fhir.utilities.npm.LockfileUtility", path, lockFileName, Integer.toString(seconds));
try {
Process process = processBuilder.start();
process.getErrorStream().transferTo(System.err);
process.getInputStream().transferTo(System.out);
process.waitFor();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
});
t.start();
return t;
}
@Test
//@EnabledOnOs(OS.LINUX)
public void testCacheCleanupForUnlockedLockFiles() throws IOException, InterruptedException {
@ -150,34 +168,19 @@ public class FilesystemPackageManagerTests {
String lockFileName = packageAndVersion + ".lock";
//Now sneak in a new lock file and directory:
File lockFile = ManagedFileAccess.file(pcmPath, lockFileName);
lockFile.createNewFile();
//lockFile.createNewFile();
File directory = ManagedFileAccess.file(pcmPath, packageAndVersion);
directory.mkdir();
// We can't create a lock file from within the same JVM, so we have to use the flock utility, which is OS dependent.
// The following works for Linux only.
ProcessBuilder processBuilder = new ProcessBuilder("flock", lockFileName, "--command", "sleep 10");
processBuilder.directory(new File(pcmPath));
processBuilder.start();
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.schedule(()->{
try {
Utilities.clearDirectory(directory.getAbsolutePath());
directory.delete();
} catch (IOException e) {
throw new RuntimeException(e);
}
lockFile.delete();
}, 15, TimeUnit.SECONDS);
Thread lockingThread = lockWaitAndDelete(pcmPath, lockFileName, 10);
Thread.sleep(200);
IOException ioException = assertThrows(IOException.class, () -> { pcm.loadPackageFromCacheOnly("example.fhir.uv.myig", "1.2.3"); });
ioException.printStackTrace();
lockingThread.join();
}
/**

View File

@ -0,0 +1,44 @@
package org.hl7.fhir.utilities.npm;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Paths;
public class LockfileUtility {
public static void main(String[] args) {
String lockFileName = args[1];
String path = args[0];
int seconds = Integer.parseInt(args[2]);
try {
lockWaitAndDelete(path, lockFileName, seconds);
} catch (InterruptedException | IOException e) {
throw new RuntimeException(e);
}
}
private static void lockWaitAndDelete(String path, String lockFileName, int seconds) throws InterruptedException, IOException {
File file = Paths.get(path,lockFileName).toFile();
try (FileChannel channel = new RandomAccessFile(file.getAbsolutePath(), "rw").getChannel()) {
FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
if (fileLock != null) {
System.out.println("File "+lockFileName+" is locked. Waiting for " + seconds + " seconds to release");
Thread.sleep(seconds * 1000L);
fileLock.release();
System.out.println("File "+lockFileName+" is released.");
channel.close();
}}finally {
if (file.exists()) {
file.delete();
}
}
}
}