package uk.ac.vamsas.client.simpleclient; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.ReadableByteChannel; /** * @author JimP * */ public class NativeLock extends Lock { protected FileLock lock = null; /** * @param lockfile * @param block true means thread will block until a lock is obtained. */ public NativeLock(File lockfile, boolean block) { super(lockfile); // try and get a lock. lock = null; try { /*if (!lockfile.createNewFile()) { log.warn("Failed to create locked file "+lockfile); return; } */ rafile=new RandomAccessFile(lockfile,"rw"); if (block) lock = rafile.getChannel().lock(); else lock = rafile.getChannel().tryLock(); if (lock==null || !lock.isValid()) { // failed to get lock. Close the file channel log.debug("failed to get lock for "+lockfile); rafile.getChannel().close(); lock=null; } } catch (FileNotFoundException e) { // log.debug("Lock failed - normal behaviour for windows locking."); //log.error("Error! Couldn't create a lockfile at " // + lockfile.getAbsolutePath(), e); } catch (IOException e) { log.error("Error! Problems with IO when creating a lock on " + lockfile.getAbsolutePath(),e); } // catch (Exception ) } public boolean isLocked() { if (lock != null && lock.isValid()) { return true; } return false; } public void release() { release(true); } public void release(boolean closeChannel) { if (lock==null) return; try { // channel.close should be called before release() for rigourous locking. if (lock.isValid() && rafile!=null && rafile.getFD().valid() && rafile.getChannel()!=null) { if (closeChannel && rafile.getChannel().isOpen()) { rafile.close(); rafile=null; } else { // just release the lock without doing anything to the channe;l if (lock!=null && lock.isValid()) lock.release(); } } } catch (IOException e) { log.warn("Whilst releasing lock",e); } lock=null; } /** * gets Locked Stream for reading from * @param atStart true to start reading at beginning of file. * @return null if file not locked * @throws IOException */ public FileInputStream getFileInputStream(boolean atStart) throws IOException { if (!isLocked()) return null; if (atStart) rafile.seek(0); return new FileInputStream(rafile.getFD()); } /** * gets Locked stream to write to * FileInput always starts at the *end* of the file (after any truncation) * @param clear true means file will be cleared to zero length * @return null if file is not locked * @throws IOException */ public FileOutputStream getFileOutputStream(boolean clear) throws IOException { if (!isLocked()) return null; if (clear) { rafile.seek(0); rafile.setLength(0); } else rafile.seek(rafile.length()); return new LockedFileOutputStream(rafile.getFD()); } /** * return buffered output stream to locked file. * @param clear - true means file is truncated to 0 length before writing * @return */ public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException { OutputStream fos = getFileOutputStream(clear); if (fos!=null) return new BufferedOutputStream(fos); return null; } /** * @see uk.ac.vamsas.client.simpleclient.Lock#finalize() */ protected void finalize() throws Throwable { release(true); // we explicitly lose the lock here. // log.debug("lock closing through garbage collection ?"); super.finalize(); } /* (non-Javadoc) * @see uk.ac.vamsas.client.simpleclient.Lock#getLength() */ public long length() { if (isLocked()){ try { return rafile.length(); } catch (Exception e) { log.debug("getLength exception:",e); } } return -1; } public RandomAccessFile getRaFile() throws IOException { if (isLocked()) return rafile; else log.debug("Failed to getRaFile on "+target); return null; } public FileChannel getRaChannel() throws IOException { if (isLocked()) return rafile.getChannel(); else log.debug("Failed to getRaChannel on "+target); return null; } public boolean isTargetLockFile(File afile) { if (isLocked() && target.equals(afile)) return true; return false; } }