package org.apache.archiva.common.filelock;
/*
* 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.
*/
import edu.umd.cs.mtc.MultithreadedTestCase;
import edu.umd.cs.mtc.TestFramework;
import org.junit.Assert;
import org.junit.Before;
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.FileNotFoundException;
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;
//import org.apache.commons.io.IOUtils;
/**
* @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 ConcurrentFileWrite
extends MultithreadedTestCase {
AtomicInteger success = new AtomicInteger(0);
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");
ConcurrentFileWrite(FileLockManager fileLockManager)
throws IOException {
this.fileLockManager = fileLockManager;
//file.createNewFile();
}
@Override
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 {
try {
logger.info("thread1");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread1 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread2()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread2");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread2 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread3()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread3");
Lock lock = fileLockManager.readFileLock(this.file);
try {
Files.copy(Paths.get(lock.getFile().getPath()),
new FileOutputStream(File.createTempFile("foo", ".jar")));
} finally {
fileLockManager.release(lock);
}
logger.info("thread3 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread4()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread4");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread4 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread5()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread5");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread5 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread6()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread6");
Lock lock = fileLockManager.readFileLock(this.file);
try {
Files.copy(lock.getFile().toPath(), new FileOutputStream(File.createTempFile("foo", ".jar")));
} finally {
fileLockManager.release(lock);
}
logger.info("thread6 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread7()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread7");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread7 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread8()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread8");
Lock lock = fileLockManager.readFileLock(this.file);
try {
Files.copy(lock.getFile().toPath(), new FileOutputStream(File.createTempFile("foo", ".jar")));
} finally {
fileLockManager.release(lock);
}
logger.info("thread8 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread9()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread9");
Lock lock = fileLockManager.writeFileLock(this.file);
try {
lock.getFile().delete();
copyFile(largeJar.toPath(), lock.getFile().toPath());
} finally {
fileLockManager.release(lock);
}
logger.info("thread9 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
public void thread10()
throws FileLockException, FileLockTimeoutException, IOException {
try {
logger.info("thread10");
Lock lock = fileLockManager.readFileLock(this.file);
try {
Files.copy(lock.getFile().toPath(), new FileOutputStream(File.createTempFile("foo", ".jar")));
} finally {
fileLockManager.release(lock);
}
logger.info("thread10 ok");
success.incrementAndGet();
} catch (Throwable e) {
logger.error("Error occured " + e.getMessage());
e.printStackTrace();
throw e;
}
}
}
@Before
public void initialize() {
fileLockManager.setSkipLocking(false);
fileLockManager.clearLockFiles();
}
@Test
public void testWrite()
throws Throwable {
ConcurrentFileWrite concurrentFileWrite = new ConcurrentFileWrite(fileLockManager);
//concurrentFileWrite.setTrace( true );
TestFramework.runManyTimes(concurrentFileWrite, 10, TestFramework.DEFAULT_CLOCKPERIOD, 20);
logger.info("success: {}", concurrentFileWrite.success);
Assert.assertEquals(100, concurrentFileWrite.success.intValue());
}
}