updated test cases for spring 2006 schema, and major debug of locking system
[vamsas.git] / src / org / vamsas / client / simpleclient / SessionFile.java
index bd2dc44..c9f9e67 100644 (file)
@@ -7,6 +7,8 @@ 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;
@@ -32,23 +34,11 @@ public class SessionFile {
       fileLock.release();// tidy up invalid lock
       fileLock=null;
     }
-    if (extantlock!=null)
+    if (extantlock!=null && extantlock.isLocked())
       fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock.
     return lockFile();
   }
-
-  /**
-   * Get a lock for the SessionFile
-   * 
-   * @return true if lock was made
-   */
-  protected boolean lockFile() {
-    if (fileLock != null)
-      if (fileLock.isLocked())
-        return true;
-      else 
-        // lock failed for some reason.
-        fileLock.release();
+  private boolean ensureSessionFile() {
     if (sessionFile != null) {
       if (!sessionFile.exists()) {
         // create new file
@@ -62,27 +52,46 @@ public class SessionFile {
           return false;
         }
       }
-      // TODO: see if we need to loop-wait for locks or they just block until
-      // lock is made...
-      long tries=500;
-      do {
-        tries--;
-        if (fileLock!=null && !fileLock.isLocked()) {
-          fileLock.release();
-          try { Thread.sleep(5); } catch (Exception e) {};
-        }
-        fileLock = LockFactory.getLock(sessionFile); // 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();    
-    } else
-      log.error("lockFile called for non-initialised SessionFile!");
-  
-    // no lock possible
+      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.
@@ -109,10 +118,18 @@ public class SessionFile {
     if (lockFile(extantLock)) {
       try {
         tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);
-        FileOutputStream tos = new FileOutputStream(tempfile);
-        tos.getChannel().transferFrom(fileLock.rafile.getChannel(), 0,
-            fileLock.rafile.length());
-        tos.close();
+        if (fileLock.length()>0) {
+          FileOutputStream tos = new FileOutputStream(tempfile);
+          ReadableByteChannel channel;
+          tos.getChannel().transferFrom(channel=fileLock.getRaChannel(), 0,
+              fileLock.length());
+          tos.close();
+          if (!channel.isOpen())
+            throw new Error(tos.getChannel().getClass()+".transferFrom closes source channel!");
+          if (!lockFile(extantLock))
+            throw new Error("Lost lock for "+sessionFile.getName()+" after backup.");
+          
+        }
       } catch (FileNotFoundException e1) {
         log.warn("Can't create temp file for "+sessionFile.getName(),e1);
         tempfile=null;
@@ -136,11 +153,21 @@ public class SessionFile {
       throw new IOException("Null SessionFile in newData.");
       
     if (!lockFile(extantLock))
-      log.error("Failed to get write lock for "+sessionFile);
+      throw new IOException("Failed to get write lock for "+sessionFile);
     if (!newData.lockFile())
-      log.warn("Failed to get lock for updateFrom "+newData.sessionFile);
-    fileLock.rafile.getChannel().transferFrom(newData.fileLock.rafile.getChannel(), 0, 
-        newData.fileLock.rafile.length());
+      throw new IOException("Failed to get lock for updateFrom "+newData.sessionFile);
+    RandomAccessFile nrafile = newData.fileLock.getRaFile();
+    nrafile.seek(0);
+    RandomAccessFile trafile = fileLock.getRaFile();
+    /*long tries=5000;
+    while (trafile==null && --tries>0) {
+      log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");
+      lockFile();
+      trafile = fileLock.getRaFile();
+    }*/
+    trafile.seek(0);
+    trafile.getChannel().transferFrom(nrafile.getChannel(), 0, 
+        nrafile.length());
   }
   /**
    * remove all trace of the sessionFile file