Stabilised file lock implementation and tests

This commit is contained in:
Martin Stockhammer 2016-10-26 23:25:50 +02:00
parent 60080379a6
commit 8dc5e696d2
3 changed files with 50 additions and 23 deletions

View File

@ -31,6 +31,7 @@
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author Olivier Lamy
@ -51,7 +52,6 @@ public class DefaultFileLockManager
private int timeout = 0;
@Override
public Lock readFileLock( File file )
throws FileLockException, FileLockTimeoutException
@ -162,20 +162,18 @@ public Lock writeFileLock( File file )
}
}
Lock current = lockFiles.get( file );
try
{
Lock current = lockFiles.get( file );
if ( current != null )
{
log.debug( "write lock file exist continue wait" );
continue;
}
lock = new Lock( file, true );
createNewFileQuietly( file );
lock.openLock( true, timeout > 0 );
lock = new Lock(file, true);
createNewFileQuietly(file);
lock.openLock(true, timeout > 0);
acquired = true;
}
catch ( FileNotFoundException e )
@ -191,12 +189,29 @@ public Lock writeFileLock( File file )
}
catch ( IOException e )
{
if (lock!=null && lock.isValid()) {
try {
lock.close();
} catch (IOException ex) {
// Ignore
}
}
throw new FileLockException( e.getMessage(), e );
}
catch ( IllegalStateException e )
catch ( Throwable e )
{
if (lock!=null && lock.isValid()) {
try {
lock.close();
} catch (IOException ex) {
// Ignore
} finally {
lock = null;
}
}
log.debug( "openLock {}:{}", e.getClass(), e.getMessage() );
}
}
Lock current = lockFiles.putIfAbsent( file, lock );

View File

@ -90,7 +90,7 @@ public boolean isShared()
public boolean isValid()
{
return this.fileLock.isValid();
return this.fileLock!=null && this.fileLock.isValid();
}
public Map<Thread, AtomicInteger> getFileClients()

View File

@ -35,7 +35,9 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.atomic.AtomicInteger;
@ -83,6 +85,22 @@ public void initialize()
}
// Files.copy is not atomic so have to try several times in
// a multithreaded test
private void copyFile(Path source, Path destination) {
int attempts=10;
boolean finished = false;
while(!finished && attempts-->0) {
try {
Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES);
finished=true;
} catch (IOException ex) {
//
}
}
}
public void thread1()
throws FileLockException, FileLockTimeoutException, IOException
{
@ -91,8 +109,7 @@ public void thread1()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -110,8 +127,7 @@ public void thread2()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -147,8 +163,7 @@ public void thread4()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -166,8 +181,7 @@ public void thread5()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -202,8 +216,7 @@ public void thread7()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -238,8 +251,7 @@ public void thread9()
try
{
lock.getFile().delete();
Files.copy( largeJar.toPath(), lock.getFile().toPath(), StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES );
copyFile( largeJar.toPath(), lock.getFile().toPath());
}
finally
{
@ -283,9 +295,9 @@ public void testWrite()
{
ConcurrentFileWrite concurrentFileWrite = new ConcurrentFileWrite( fileLockManager );
//concurrentFileWrite.setTrace( true );
TestFramework.runOnce( concurrentFileWrite );
TestFramework.runManyTimes( concurrentFileWrite, 10);
logger.info( "success: {}", concurrentFileWrite.success );
Assert.assertEquals( 10, concurrentFileWrite.success.intValue() );
Assert.assertEquals( 100, concurrentFileWrite.success.intValue() );
}