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.RandomAccessFile; import java.nio.channels.ReadableByteChannel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Basic methods for classes handling locked IO on files * monitored by all (simpleclient) clients in a vamsas session. * @author jimp *TODO: support non nio file locking capable systems */ public class SessionFile { private static Log log = LogFactory.getLog(SessionFile.class); protected File sessionFile; protected Lock fileLock = null; protected SessionFile(File file) { super(); sessionFile = file; } protected boolean lockFile(Lock extantlock) { if (fileLock!=null && !fileLock.isLocked()) { fileLock.release();// tidy up invalid lock fileLock=null; } if (extantlock!=null && extantlock.isLocked()) fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock. return lockFile(); } private boolean ensureSessionFile() { if (sessionFile != null) { if (!sessionFile.exists()) { // create new file try { if (!sessionFile.createNewFile()) { log.error("Failed to create file prior to locking: "+sessionFile); return false; } } catch (IOException e) { log.error("Exception when trying to create file "+sessionFile, e); return false; } } return true; } log.error("ensureSessionFile called for non-initialised SessionFile!"); return false; } /** * Get a lock for the SessionFile * * @return true if lock was made */ protected boolean lockFile() { if (fileLock != null) { if (fileLock.isLocked()) { if (!ensureSessionFile()) return false; return true; } else { // lock failed for some reason. fileLock.release(); log.info("Unexpected session file lock failure. Trying to get it again."); fileLock=null; } } if (!ensureSessionFile()) return false; // TODO: see if we need to loop-wait for locks or they just block until // lock is made... long tries=5000; do { tries--; if (fileLock==null || !fileLock.isLocked()) { //try { Thread.sleep(1); } catch (Exception e) {}; fileLock = LockFactory.getLock(sessionFile,true); // TODO: wait around if we can't get the lock. } } while (tries>0 && !fileLock.isLocked()); if (!fileLock.isLocked()) log.error("Failed to get lock for "+sessionFile); // fileLock = new Lock(sessionFile); return fileLock.isLocked(); } /** * Explicitly release the SessionFile's lock. * * @return true if lock was released. */ protected void unlockFile() { if (fileLock != null) { fileLock.release(); fileLock = null; } } /** * Makes a backup of the sessionFile. * @return Backed up SessionFile or null if failed to make backup. */ protected File backupSessionFile() { return backupSessionFile(fileLock, sessionFile.getName(),".old", sessionFile.getParentFile()); } protected File backupSessionFile(Lock extantLock, String backupPrefix, String backupSuffix, File backupDir) { File tempfile=null; if (lockFile(extantLock)) { try { tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir); long sourceln = fileLock.length(); if (sourceln>0) { FileOutputStream tos = new FileOutputStream(tempfile); ReadableByteChannel channel; channel = fileLock.getRaChannel().position(0); long ntrans = 0; while (ntrans0) { log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer."); lockFile(); trafile = fileLock.getRaFile(); }*/ // TODO JBPNote: attempt to ensure save really saves the VamDoc.jar file trafile.seek(0); trafile.getChannel().transferFrom(nrafile.getChannel(), 0, nrafile.length()); // JBPNote: attempt to close the streams to flush the data out // trafile.close(); //nrafile.close(); } /** * remove all trace of the sessionFile file * */ protected void eraseExistence() { unlockFile(); if (sessionFile!=null) { sessionFile.delete(); sessionFile = null; } } /* (non-Javadoc) * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean) */ public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException { lockFile(); return fileLock.getBufferedInputStream(atStart); } /* (non-Javadoc) * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean) */ public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException { lockFile(); return fileLock.getBufferedOutputStream(clear); } /* (non-Javadoc) * @see uk.ac.vamsas.client.simpleclient.Lock#getFileInputStream(boolean) */ public FileInputStream getFileInputStream(boolean atStart) throws IOException { lockFile(); return fileLock.getFileInputStream(atStart); } /* (non-Javadoc) * @see uk.ac.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean) */ public FileOutputStream getFileOutputStream(boolean clear) throws IOException { lockFile(); return fileLock.getFileOutputStream(clear); } }