gatk-3.8/java/src/org/broadinstitute/sting/utils/file/FSLockWithShared.java

131 lines
4.1 KiB
Java

package org.broadinstitute.sting.utils.file;
import org.apache.log4j.Logger;
import org.broadinstitute.sting.utils.StingException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
/**
* a quick implementation of a file based lock, using the Java NIO classes
*/
public class FSLockWithShared {
// connect to the logger
private final static Logger logger = Logger.getLogger(FSLockWithShared.class);
// the file we're attempting to lock
private final File file;
// the file lock
private FileLock lock = null;
// the file channel we open
private FileChannel channel = null;
/**
* create a file system, given a base file to which a lock string gets appended.
* @param baseFile File descriptor of file to lock
*/
public FSLockWithShared(File baseFile) {
file = baseFile;
}
/**
* Get a shared (read) lock on a file
* Cannot get shared lock if it does not exist
* @return boolean true if we obtained a lock
*/
public boolean sharedLock() {
// get read-only file channel
try {
channel = new RandomAccessFile(file, "r").getChannel();
}
catch (IOException e) {
logger.debug("Unable to lock file (could not open read only file channel)");
return false;
}
// get shared lock (third argument is true)
try {
lock = channel.tryLock(0, Long.MAX_VALUE, true);
if (lock == null) {
logger.debug("Unable to lock file because there is already a lock active.");
return false;
}
}
catch (ClosedChannelException e) {
logger.debug("Unable to lock file because the file channel is closed.");
return false;
}
catch (OverlappingFileLockException e) {
logger.debug("Unable to lock file because you already have a lock on this file.");
return false;
}
catch (IOException e) {
logger.debug("Unable to lock file (due to IO exception)");
return false;
}
return true;
}
/**
* Get an exclusive lock on a file
* @return boolean true if we obtained a lock
*/
public boolean exclusiveLock() {
// read/write file channel is necessary for exclusive lock
try {
channel = new RandomAccessFile(file, "rw").getChannel();
}
catch (Exception e) {
logger.debug("Unable to lock file (could not open read/write file channel)");
// do we need to worry about deleting file here? Does RandomAccessFile will only create file if successful?
return false;
}
// get exclusive lock (third argument is false)
try {
lock = channel.tryLock(0, Long.MAX_VALUE, false);
if (lock == null) {
logger.debug("Unable to lock file because there is already a lock active.");
return false;
}
else return true;
}
catch (ClosedChannelException e) {
logger.debug("Unable to lock file because the file channel is closed.");
return false;
}
catch (OverlappingFileLockException e) {
logger.debug("Unable to lock file because you already have a lock on this file.");
return false;
}
catch (IOException e) {
logger.debug("Unable to lock file (due to IO exception)");
return false;
}
}
/**
* unlock the file
*
* note: this allows unlocking a file that failed to lock (no required user checks on null locks).
*/
public void unlock() {
try {
if (lock != null)
lock.release();
if (channel != null)
channel.close();
}
catch (Exception e) {
throw new StingException("An error occurred while unlocking file", e);
}
}
}