]> source.dussan.org Git - archiva.git/commitdiff
Stabilised file lock implementation and tests
authorMartin Stockhammer <martin_s@apache.org>
Wed, 26 Oct 2016 21:25:50 +0000 (23:25 +0200)
committerMartin Stockhammer <martin_s@apache.org>
Wed, 26 Oct 2016 21:33:09 +0000 (23:33 +0200)
archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/DefaultFileLockManager.java
archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
archiva-modules/archiva-base/archiva-filelock/src/test/java/org/apache/archiva/common/filelock/DefaultFileLockManagerTest.java

index ee4fb35be54ebc3644656190e812336c3ac4ac58..2ce2f188c2912f02d51cc0f5c159438c4fad90fd 100644 (file)
@@ -31,6 +31,7 @@ import java.io.RandomAccessFile;
 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 class DefaultFileLockManager
                 }
             }
 
-            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 class DefaultFileLockManager
             }
             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 );
index bd4afcb61250fe12e022ccabf154925d079e0958..17b19c0b0a44cc6641c21c8f37de7e15709775b3 100644 (file)
@@ -90,7 +90,7 @@ public class Lock
 
     public boolean isValid()
     {
-        return this.fileLock.isValid();
+        return this.fileLock!=null && this.fileLock.isValid();
     }
 
     public Map<Thread, AtomicInteger> getFileClients()
index cc63e0c3afcb164bd378dc9046975562b7feb381..96186612e9eb80264ced8c1e1d364e066cf9c7d3 100644 (file)
@@ -35,7 +35,9 @@ import javax.inject.Named;
 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 class DefaultFileLockManagerTest
 
         }
 
+        // 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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
             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 class DefaultFileLockManagerTest
     {
         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() );
     }