/* * This file is part of the Vamsas Client version 0.1. * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, * Andrew Waterhouse and Dominik Lindner. * * Earlier versions have also been incorporated into Jalview version 2.4 * since 2008, and TOPALi version 2 since 2007. * * The Vamsas Client is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Vamsas Client is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Vamsas Client. If not, see . */ 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; } }