locking for windows (XP) partly debugged. ClientsFileTest watchers do not behave...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Thu, 23 Mar 2006 11:41:09 +0000 (11:41 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Thu, 23 Mar 2006 11:41:09 +0000 (11:41 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@201 be28352e-c001-0410-b1a7-c7978e42abec

src/org/vamsas/client/simpleclient/ClientsFile.java
src/org/vamsas/client/simpleclient/Lock.java
src/org/vamsas/client/simpleclient/LockedFileOutputStream.java [new file with mode: 0644]
src/org/vamsas/client/simpleclient/SessionFile.java
src/org/vamsas/client/simpleclient/SimpleClientAppdata.java
src/org/vamsas/client/simpleclient/VamsasArchive.java

index 598bfdd..d8abd2b 100644 (file)
@@ -43,8 +43,8 @@ public class ClientsFile extends ListFile {
       try {
         ClientHandle[] clients=null;
         if (this.fileLock.rafile.length()>0) {
-          ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(
-              new java.io.FileInputStream(sessionFile)));
+          
+          ObjectInputStream is = new ObjectInputStream(fileLock.getBufferedInputStream(true));
           Object o;
           o=is.readObject();
           if (o!=null) {
@@ -231,11 +231,14 @@ public class ClientsFile extends ListFile {
       File templist = backupSessionFile();
       if (templist != null) {
         try {
-          fileLock.rafile.setLength(0);
-          ObjectOutputStream os = new ObjectOutputStream(
-              new BufferedOutputStream(new FileOutputStream(this.sessionFile)));
+          // fileLock.rafile.setLength(0);
+          ObjectOutputStream os = 
+            new ObjectOutputStream(fileLock.getBufferedOutputStream(true));
+          
+//              new BufferedOutputStream(new FileOutputStream(this.sessionFile)));
+          //    new BufferedOutputStream(new FileOutputStream(this.fileLock.rafile.getFD())));
           os.writeObject(clients);
-          os.close();
+          os.close(); // close destroys lock!
           // All done - remove the backup.
           templist.delete();
           templist = null;
index dfc978e..b49cdf5 100644 (file)
@@ -1,11 +1,16 @@
 package org.vamsas.client.simpleclient;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.nio.channels.FileLock;
 
+import org.apache.commons.logging.LogFactory;
+
 /**
  * transient object representing a file lock
  * This lock should hold for all processes interacting in a session.
@@ -15,6 +20,7 @@ import java.nio.channels.FileLock;
  */
 
 public class Lock {
+  org.apache.commons.logging.Log log = LogFactory.getLog(Lock.class);
   FileLock lock = null;
   RandomAccessFile rafile=null;
   /**
@@ -29,21 +35,25 @@ public class Lock {
     try {
       if (!lockfile.exists())
         if (!lockfile.createNewFile()) {
+          log.warn("Failed to create locked file "+lockfile);
           return;
         }
       
       lock = (rafile=new RandomAccessFile(lockfile,"rw")).getChannel().tryLock();
-      if (lock==null || !lock.isValid())
+      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) {
-      System.err.println("Error! Couldn't create a lockfile at "
-          + lockfile.getAbsolutePath());
-      e.printStackTrace();
+      //
+      log.debug("Lock failed - normal behaviour for windows locking.");
+      //log.error("Error! Couldn't create a lockfile at "
+      //  + lockfile.getAbsolutePath(), e);
     } catch (IOException e) {
-      System.err.println("Error! Problems with IO when creating a lock on "
-          + lockfile.getAbsolutePath());
-      e.printStackTrace();
+      log.error("Error! Problems with IO when creating a lock on "
+          + lockfile.getAbsolutePath(),e);
     }
   }
   
@@ -55,19 +65,73 @@ public class Lock {
   }
   public void release() {
     try {
-      // TODO: verify that channel.close should be called after release() for rigourous locking. 
-      if (lock!=null && lock.isValid())
-        lock.release();
-      if (rafile!=null && rafile.getChannel().isOpen())
-        rafile.getChannel().close();
+      // TODO: verify that channel.close should be called after release() for rigourous locking.
+      if (rafile!=null && rafile.getChannel()!=null) {
+        if (rafile.getChannel().isOpen()) {
+          if (lock!=null && lock.isValid())
+            lock.release();
+          if (rafile!=null && rafile.getChannel().isOpen())
+            rafile.getChannel().close();
+        }
+      }
     } catch (IOException e) {
-      // TODO Auto-generated catch block
-      e.printStackTrace(System.err);
+      log.warn("Whilst releasing lock",e);
     }
     lock=null;
     rafile=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.setLength(0);
+    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 {
+    FileOutputStream fos = getFileOutputStream(clear);
+    if (fos!=null)
+      return new BufferedOutputStream(fos);
+    return null;
+  }
+
+  /**
+   * return buffered input stream for locked file.
+   * @param atStart - true means read from begining of file
+   * @return null if file is not locked.
+   */
+  public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException {
+    FileInputStream fis = getFileInputStream(atStart);
+    if (fis!=null)
+      return new BufferedInputStream(fis);
+    return null;
+  }
   /* Explicitly release lock (probably don't need to do this!)
    * @see java.lang.Object#finalize()
    */
diff --git a/src/org/vamsas/client/simpleclient/LockedFileOutputStream.java b/src/org/vamsas/client/simpleclient/LockedFileOutputStream.java
new file mode 100644 (file)
index 0000000..2c12974
--- /dev/null
@@ -0,0 +1,73 @@
+/**\r
+ * \r
+ */\r
+package org.vamsas.client.simpleclient;\r
+\r
+import java.io.File;\r
+import java.io.FileDescriptor;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * @author Jim\r
+ *\r
+ */\r
+public class LockedFileOutputStream extends FileOutputStream {\r
+\r
+  /**\r
+   * @param file\r
+   * @throws FileNotFoundException\r
+   */\r
+  public LockedFileOutputStream(File file) throws FileNotFoundException {\r
+    super(file);\r
+    // TODO Auto-generated constructor stub\r
+  }\r
+\r
+  /**\r
+   * @param file\r
+   * @param append\r
+   * @throws FileNotFoundException\r
+   */\r
+  public LockedFileOutputStream(File file, boolean append)\r
+      throws FileNotFoundException {\r
+    super(file, append);\r
+    // TODO Auto-generated constructor stub\r
+  }\r
+\r
+  /**\r
+   * @param fdObj\r
+   */\r
+  public LockedFileOutputStream(FileDescriptor fdObj) {\r
+    super(fdObj);\r
+    // TODO Auto-generated constructor stub\r
+  }\r
+\r
+  /**\r
+   * @param name\r
+   * @throws FileNotFoundException\r
+   */\r
+  public LockedFileOutputStream(String name) throws FileNotFoundException {\r
+    super(name);\r
+    // TODO Auto-generated constructor stub\r
+  }\r
+\r
+  /**\r
+   * @param name\r
+   * @param append\r
+   * @throws FileNotFoundException\r
+   */\r
+  public LockedFileOutputStream(String name, boolean append)\r
+      throws FileNotFoundException {\r
+    super(name, append);\r
+    // TODO Auto-generated constructor stub\r
+  }\r
+  /**\r
+   * closes - actually just flushes the stream instead.\r
+   */\r
+  public void close() throws IOException {\r
+    // TODO Auto-generated method stub\r
+    super.flush();\r
+  }\r
+  \r
+}\r
index 0eabf6d..d33f2f8 100644 (file)
@@ -27,8 +27,10 @@ public class SessionFile {
   protected boolean lockFile(Lock extantlock) {
     if (fileLock!=null && !fileLock.isLocked()) {
       fileLock.release();// tidy up invalid lock
+      fileLock=null;
     }
-    fileLock=extantlock;
+    if (extantlock!=null)
+      fileLock=extantlock;
     return lockFile();
   }
 
@@ -60,11 +62,15 @@ public class SessionFile {
       }
       // TODO: see if we need to loop-wait for locks or they just block until
       // lock is made...
+      long tries=500;
       do {
-        if (fileLock!=null)
+        tries--;
+        if (fileLock!=null && !fileLock.isLocked())
           fileLock.release();
           fileLock = new Lock(sessionFile); // TODO: wait around if we can't get the lock.
-      } while (!fileLock.isLocked());
+      } while (tries>0 && !fileLock.isLocked());
+      if (!fileLock.isLocked())
+        log.error("Failed to get lock for "+sessionFile);
       // fileLock = new Lock(sessionFile);
       return fileLock.isLocked();    
     } else
index a2d8912..95362aa 100644 (file)
@@ -343,8 +343,7 @@ public class SimpleClientAppdata implements IClientAppdata {
       apdfile.lockFile();
       // LATER: Refactor these local AppDatastream IO stuff to their own class.
       JarOutputStream dstrm = 
-        new JarOutputStream(
-            new BufferedOutputStream(new java.io.FileOutputStream(apdfile.sessionFile)));
+        new JarOutputStream(apdfile.fileLock.getBufferedOutputStream(true));
       if (!clientOrUser) {
         newAppDataStream = dstrm;
       } else {
index c485124..c58c5f3 100644 (file)
@@ -533,7 +533,7 @@ public class VamsasArchive {
       rchive = new SessionFile(archive);
     if (!rchive.lockFile()) 
       throw new IOException("Failed to get lock on file "+archive);
-    newarchive = new JarOutputStream(new BufferedOutputStream(new java.io.FileOutputStream(archive)));  
+    newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true));  
     entries = new Hashtable();
   }
   public void putVamsasDocument(VamsasDocument doc) throws IOException,