mirror of https://github.com/apache/archiva.git
add a new module for file locking
git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1550396 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
074386d154
commit
6b23332e9d
|
@ -39,6 +39,16 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva.redback.components.registry</groupId>
|
||||
<artifactId>spring-registry-commons</artifactId>
|
||||
|
@ -52,41 +62,41 @@
|
|||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils-core</artifactId>
|
||||
</exclusion>
|
||||
<!-- targeting JDK 1.4, xml parser/apis not needed -->
|
||||
<exclusion>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xerces</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xml-apis</groupId>
|
||||
<artifactId>xml-apis</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>servletapi</groupId>
|
||||
<artifactId>servletapi</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant-optional</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils-core</artifactId>
|
||||
</exclusion>
|
||||
<!-- targeting JDK 1.4, xml parser/apis not needed -->
|
||||
<exclusion>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xerces</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>xml-apis</groupId>
|
||||
<artifactId>xml-apis</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>servletapi</groupId>
|
||||
<artifactId>servletapi</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant-optional</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.apache.archiva</groupId>
|
||||
<artifactId>archiva-base</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>archiva-filelock</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>Archiva Base :: FileLock</name>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-jcl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.multithreadedtc</groupId>
|
||||
<artifactId>multithreadedtc</artifactId>
|
||||
<version>1.01</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>org.apache.archiva.common</Bundle-SymbolicName>
|
||||
<Bundle-Version>${project.version}</Bundle-Version>
|
||||
<Export-Package>
|
||||
org.apache.archiva.common*;version=${project.version}
|
||||
</Export-Package>
|
||||
<Import-Package>
|
||||
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<buildDirectory>${project.build.directory}</buildDirectory>
|
||||
<java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.rat</groupId>
|
||||
<artifactId>apache-rat-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,177 @@
|
|||
package org.apache.archiva.common.filelock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author Olivier Lamy
|
||||
*/
|
||||
@Service("fileLockManager#default")
|
||||
public class DefaultFileLockManager
|
||||
implements FileLockManager
|
||||
{
|
||||
private static final ConcurrentMap<File, Lock> lockFiles = new ConcurrentHashMap<File, Lock>( 64 );
|
||||
|
||||
private boolean skipLocking = false;
|
||||
|
||||
private Logger log = LoggerFactory.getLogger( getClass() );
|
||||
|
||||
@Override
|
||||
public Lock readFileLock( File file )
|
||||
throws FileLockException
|
||||
{
|
||||
if ( skipLocking )
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Lock( file, false );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new FileLockException( e.getMessage(), e );
|
||||
}
|
||||
}
|
||||
Lock lock = lockFiles.get( file );
|
||||
if ( lock == null )
|
||||
{
|
||||
try
|
||||
{
|
||||
lock = new Lock( file, false );
|
||||
Lock current = lockFiles.putIfAbsent( file, lock );
|
||||
if ( current != null )
|
||||
{
|
||||
lock = current;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new FileLockException( e.getMessage(), e );
|
||||
}
|
||||
catch ( OverlappingFileLockException e )
|
||||
{
|
||||
log.debug( "OverlappingFileLockException: {}", e.getMessage() );
|
||||
if ( lock == null )
|
||||
{
|
||||
lock = lockFiles.get( file );
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME add a timeout on getting that!!!
|
||||
while ( true )
|
||||
{
|
||||
log.debug( "wait read lock" );
|
||||
synchronized ( lock )
|
||||
{
|
||||
if ( lock.getFileLock().isShared() || !lock.getFileLock().isValid() )
|
||||
{
|
||||
lock.addFileClient( Thread.currentThread() );
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
//return lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock writeFileLock( File file )
|
||||
throws FileLockException
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( skipLocking )
|
||||
{
|
||||
return new Lock( file, true );
|
||||
}
|
||||
|
||||
// FIXME add a timeout on getting that!!!
|
||||
while ( true )
|
||||
{
|
||||
Lock lock = lockFiles.get( file );
|
||||
log.debug( "wait write lock" );
|
||||
if ( lock != null )
|
||||
{
|
||||
synchronized ( lock )
|
||||
{
|
||||
if ( lock.getFileLock().isValid() || lock.getFileClients().size() > 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
lock = new Lock( file, true );
|
||||
}
|
||||
catch ( OverlappingFileLockException e )
|
||||
{
|
||||
log.debug( "OverlappingFileLockException: {}", e.getMessage() );
|
||||
if ( lock == null )
|
||||
{
|
||||
lock = lockFiles.get( file );
|
||||
}
|
||||
|
||||
lock = lockFiles.get( file );
|
||||
log.debug( "OverlappingFileLockException get: {}", lock );
|
||||
}
|
||||
Lock current = lockFiles.putIfAbsent( file, lock );
|
||||
if ( current != null )
|
||||
{
|
||||
lock = current;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new FileLockException( e.getMessage(), e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release( Lock lock )
|
||||
throws FileLockException
|
||||
{
|
||||
if ( lock == null )
|
||||
{
|
||||
log.debug( "skip releasing null" );
|
||||
return;
|
||||
}
|
||||
if ( skipLocking )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if ( lock.isWrite().get() )
|
||||
{
|
||||
lock.getFileLock().release();
|
||||
}
|
||||
synchronized ( lock )
|
||||
{
|
||||
lock.close();
|
||||
if ( lock.getFileClients().size() < 1 )
|
||||
{
|
||||
lockFiles.remove( lock.getFile() );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new FileLockException( e.getMessage(), e );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.apache.archiva.common.filelock;
|
||||
|
||||
/**
|
||||
* @author Olivier Lamy
|
||||
*/
|
||||
public class FileLockException
|
||||
extends Exception
|
||||
{
|
||||
public FileLockException( String s, Throwable throwable )
|
||||
{
|
||||
super( s, throwable );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.apache.archiva.common.filelock;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Olivier Lamy
|
||||
*/
|
||||
public interface FileLockManager
|
||||
{
|
||||
Lock writeFileLock( File file )
|
||||
throws FileLockException;
|
||||
|
||||
Lock readFileLock( File file )
|
||||
throws FileLockException;
|
||||
|
||||
void release( Lock lock )
|
||||
throws FileLockException;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.apache.archiva.common.filelock;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @author Olivier Lamy
|
||||
*/
|
||||
public class Lock
|
||||
{
|
||||
private File file;
|
||||
|
||||
private AtomicBoolean write;
|
||||
|
||||
private final Map<Thread, AtomicInteger> fileClients = new HashMap<Thread, AtomicInteger>();
|
||||
|
||||
private FileLock fileLock;
|
||||
|
||||
public Lock( File file, boolean write )
|
||||
throws FileNotFoundException, IOException
|
||||
{
|
||||
this.file = file;
|
||||
this.write = new AtomicBoolean( write );
|
||||
this.openLock( write );
|
||||
}
|
||||
|
||||
public File getFile()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
public AtomicBoolean isWrite()
|
||||
{
|
||||
return write;
|
||||
}
|
||||
|
||||
public void setFile( File file )
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void setWrite( boolean write )
|
||||
{
|
||||
this.write.set( write );
|
||||
}
|
||||
|
||||
public FileLock getFileLock()
|
||||
{
|
||||
return fileLock;
|
||||
}
|
||||
|
||||
public void setFileLock( FileLock fileLock )
|
||||
{
|
||||
this.fileLock = fileLock;
|
||||
}
|
||||
|
||||
public Map<Thread, AtomicInteger> getFileClients()
|
||||
{
|
||||
return fileClients;
|
||||
}
|
||||
|
||||
public void addFileClient( Thread thread )
|
||||
{
|
||||
this.fileClients.put( thread, new AtomicInteger( 1 ) );
|
||||
}
|
||||
|
||||
public boolean removeFileClient( Thread thread )
|
||||
{
|
||||
return this.fileClients.remove( thread ) != null;
|
||||
}
|
||||
|
||||
protected void close()
|
||||
throws IOException
|
||||
{
|
||||
if ( this.write.get() )
|
||||
{
|
||||
this.fileLock.release();
|
||||
fileClients.remove( Thread.currentThread() );
|
||||
}
|
||||
}
|
||||
|
||||
public void openLock( boolean write )
|
||||
throws IOException
|
||||
{
|
||||
fileClients.put( Thread.currentThread(), new AtomicInteger( 1 ) );
|
||||
RandomAccessFile raf = new RandomAccessFile( file, write ? "rw" : "r" );
|
||||
this.fileLock = raf.getChannel().lock( 1, 1, !write );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder( "Lock{" );
|
||||
sb.append( "file=" ).append( file );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
|
||||
default-lazy-init="true">
|
||||
|
||||
<context:annotation-config/>
|
||||
<context:component-scan base-package="org.apache.archiva.common.filelock"/>
|
||||
|
||||
|
||||
</beans>
|
Binary file not shown.
|
@ -0,0 +1,208 @@
|
|||
package org.apache.archiva.common.filelock;
|
||||
|
||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||
import edu.umd.cs.mtc.TestFramework;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Olivier Lamy
|
||||
*/
|
||||
@RunWith( SpringJUnit4ClassRunner.class )
|
||||
@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml" } )
|
||||
public class DefaultFileLockManagerTest
|
||||
{
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger( getClass() );
|
||||
|
||||
@Inject
|
||||
@Named( value = "fileLockManager#default" )
|
||||
FileLockManager fileLockManager;
|
||||
|
||||
class ConcurentFileWrite
|
||||
extends MultithreadedTestCase
|
||||
{
|
||||
|
||||
FileLockManager fileLockManager;
|
||||
|
||||
File file = new File( System.getProperty( "buildDirectory" ), "foo.txt" );
|
||||
|
||||
File largeJar = new File( System.getProperty( "basedir" ), "src/test/cassandra-all-2.0.3.jar" );
|
||||
|
||||
ConcurentFileWrite( FileLockManager fileLockManager )
|
||||
throws IOException
|
||||
{
|
||||
this.fileLockManager = fileLockManager;
|
||||
file.createNewFile();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void thread1()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread1" );
|
||||
Lock lock = fileLockManager.writeFileLock( this.file );
|
||||
try
|
||||
{
|
||||
lock.getFile().delete();
|
||||
FileUtils.copyFile( largeJar, lock.getFile() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread1 ok" );
|
||||
}
|
||||
|
||||
public void thread2()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread2" );
|
||||
Lock lock = fileLockManager.writeFileLock( this.file );
|
||||
try
|
||||
{
|
||||
lock.getFile().delete();
|
||||
FileUtils.copyFile( largeJar, lock.getFile() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread2 ok" );
|
||||
}
|
||||
|
||||
public void thread3()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread3" );
|
||||
Lock lock = fileLockManager.readFileLock( this.file );
|
||||
try
|
||||
{
|
||||
IOUtils.copy( new FileInputStream( lock.getFile() ),
|
||||
new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread3 ok" );
|
||||
}
|
||||
|
||||
public void thread4()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread4" );
|
||||
Lock lock = fileLockManager.writeFileLock( this.file );
|
||||
try
|
||||
{
|
||||
lock.getFile().delete();
|
||||
FileUtils.copyFile( largeJar, lock.getFile() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread4 ok" );
|
||||
}
|
||||
|
||||
public void thread5()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread5" );
|
||||
Lock lock = fileLockManager.writeFileLock( this.file );
|
||||
try
|
||||
{
|
||||
lock.getFile().delete();
|
||||
FileUtils.copyFile( largeJar, lock.getFile() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread5 ok" );
|
||||
}
|
||||
|
||||
public void thread6()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread6" );
|
||||
Lock lock = fileLockManager.readFileLock( this.file );
|
||||
try
|
||||
{
|
||||
IOUtils.copy( new FileInputStream( lock.getFile() ),
|
||||
new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread6 ok" );
|
||||
}
|
||||
|
||||
public void thread7()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread7" );
|
||||
Lock lock = fileLockManager.writeFileLock( this.file );
|
||||
try
|
||||
{
|
||||
lock.getFile().delete();
|
||||
FileUtils.copyFile( largeJar, lock.getFile() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread7 ok" );
|
||||
}
|
||||
|
||||
public void thread8()
|
||||
throws FileLockException, IOException
|
||||
{
|
||||
logger.info( "thread8" );
|
||||
Lock lock = fileLockManager.readFileLock( this.file );
|
||||
try
|
||||
{
|
||||
IOUtils.copy( new FileInputStream( lock.getFile() ),
|
||||
new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLockManager.release( lock );
|
||||
}
|
||||
logger.info( "thread8 ok" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrite()
|
||||
throws Throwable
|
||||
{
|
||||
ConcurentFileWrite concurentFileWrite = new ConcurentFileWrite( fileLockManager );
|
||||
//concurentFileWrite.setTrace( true );
|
||||
TestFramework.runOnce( concurentFileWrite );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
|
||||
<configuration status="debug">
|
||||
|
||||
|
||||
|
||||
<appenders>
|
||||
<Console name="console" target="SYSTEM_OUT">
|
||||
<!--PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/-->
|
||||
<PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n}" />
|
||||
</Console>
|
||||
|
||||
</appenders>
|
||||
<loggers>
|
||||
|
||||
|
||||
<logger name="org.apache.archiva.common.filelock" level="debug"/>
|
||||
|
||||
<root level="info" includeLocation="true">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
</loggers>
|
||||
</configuration>
|
||||
|
||||
|
|
@ -83,6 +83,7 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -1091,6 +1092,9 @@ public class DefaultRepositoryProxyConnectors
|
|||
}
|
||||
|
||||
target.getParentFile().mkdirs();
|
||||
// TODO file lock library
|
||||
RandomAccessFile raf;
|
||||
|
||||
if ( !temp.renameTo( target ) )
|
||||
{
|
||||
log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<modules>
|
||||
<module>archiva-test-utils</module>
|
||||
<module>archiva-common</module>
|
||||
<module>archiva-filelock</module>
|
||||
<module>archiva-model</module>
|
||||
<module>archiva-configuration</module>
|
||||
<module>archiva-checksum</module>
|
||||
|
|
|
@ -201,6 +201,7 @@ public class ArchivaDavResource
|
|||
FileInputStream is = null;
|
||||
try
|
||||
{
|
||||
// TODO file lock library
|
||||
// Write content to stream
|
||||
is = new FileInputStream( localResource );
|
||||
IOUtils.copy( is, outputContext.getOutputStream() );
|
||||
|
|
5
pom.xml
5
pom.xml
|
@ -260,6 +260,11 @@
|
|||
<artifactId>archiva-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva</groupId>
|
||||
<artifactId>archiva-filelock</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva</groupId>
|
||||
<artifactId>archiva-configuration</artifactId>
|
||||
|
|
Loading…
Reference in New Issue