new fileWatcher method passes lock for changed file back to the caller.
authorjprocter <jprocter@compbio.dundee.ac.uk>
Mon, 24 Oct 2005 13:32:28 +0000 (13:32 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Mon, 24 Oct 2005 13:32:28 +0000 (13:32 +0000)
ClientsFile methods extended to take an existing lock as a parameter.

git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@75 be28352e-c001-0410-b1a7-c7978e42abec

src/org/vamsas/client/simpleclient/ClientsFile.java
src/org/vamsas/client/simpleclient/FileWatcher.java
src/org/vamsas/test/simpleclient/ClientsFileTest.java

index c624100..e5cbc72 100644 (file)
@@ -17,7 +17,7 @@ import java.io.OutputStream;
 import java.util.Vector;
 
 /**
- * @author jim Handler for the clientsFile within a vamsas session.
+ * @author jim Handler for the clientsFile within a vamsas session thread.
  */
 public class ClientsFile {
   private File filelist;
@@ -36,14 +36,25 @@ public class ClientsFile {
 
   private Lock listlock = null;
 
+  protected boolean lockList(Lock extantlock) {
+    if (listlock!=null && !listlock.isLocked()) {
+      listlock.release();// tidy up invalid lock
+    }
+    listlock=extantlock;
+    return lockList();
+  }
   /**
    * Get a lock for the ClientsFile
    * 
    * @return true if lock was made
    */
   protected boolean lockList() {
-    if (listlock != null && listlock.isLocked())
-      return true;
+    if (listlock != null)
+      if (listlock.isLocked())
+        return true;
+      else 
+        // lock failed for some reason.
+        listlock.release();
     listlock = null;
     if (filelist != null) {
       if (filelist.exists()) {
@@ -72,11 +83,7 @@ public class ClientsFile {
    */
   protected void unlockList() {
     if (listlock != null) {
-
-      if (listlock.isLocked()) {
-        listlock.release();
-      }
-
+      listlock.release();    
       listlock = null;
     }
   }
@@ -116,7 +123,7 @@ public class ClientsFile {
     return null;
   }
   /**
-   * get the clientList from the file. May return false if lock failed!
+   * get the clientList from the file. May return null if lock failed!
    * @return clientList
    */
   public ClientHandle[] retrieveClientList() {
@@ -127,6 +134,19 @@ public class ClientsFile {
     }
     return null;
   }
+  /**
+   * get list from the locked ClientList.
+   * @param extantlock
+   * @return clientList or null if lock failed (or file was empty)
+   */
+  public ClientHandle[] retrieveClientList(Lock extantlock) {
+    if (lockList(extantlock)) {
+      ClientHandle[] clients = retrieveClientHandles();
+      unlockList();
+      return clients;
+    }
+    return null;
+  }
 
   /**
    * adds the ClientHandle to the list - if it is not unique, then the
@@ -145,14 +165,15 @@ public class ClientsFile {
 
   /**
    * removes 'me' from the session ClientList without complaint if 'me' isn't in the clientList already.
-   * @param me
+   * @param me client handle to be removed
+   * @param clientlock existing lock passed from watcher.
    */
-  public void removeClient(ClientHandle me) {
+  public void removeClient(ClientHandle me, Lock clientlock) {
     int mynum=-1;
-    if (lockList()) {
+    if (lockList(clientlock)) {
       ClientHandle[] clients = retrieveClientHandles();
       if (clients != null) {
-        if (clients[syncnum-1]!=me) {
+        if ((syncnum<=0 || syncnum>clients.length) || clients[syncnum-1]!=me) {
           for (int i = 0, j = clients.length; i < j; i++) 
             if (clients[i].equals(me)) {
               mynum=i;
index bc9f705..34897a8 100644 (file)
@@ -18,23 +18,29 @@ public class FileWatcher {
   private long lastStat[];
   boolean waslocked=false;
   boolean exists = false;
-
   /**
-   * Make a watcher for a particular file. If the file doesn't exist, the
-   * watcher will watch for its creation (and indicate a change of state) 
-   * For locked files, the removal of a lock constitutes a change of 
-   * state if the file was modified.
-   * 
-   * @param subject
+   * transient lock on subject - can be passed back to calling class
+   * to preserve new state of file for immediate reading.
    */
+  private Lock subjectLock = null;
+  
+  private void clearLock() {
+    if (subjectLock!=null)
+      subjectLock.release();
+    subjectLock=null;
+  }
+  
   private boolean checkLock() {
     if (subject!=null && subject.exists()) {
-      Lock tl = new Lock(subject);
-      if (tl.isLocked()) {
-        tl.release();
+      if (subjectLock!=null) {
+        subjectLock.release();
+      }
+      subjectLock = new Lock(subject);
+      if (subjectLock.isLocked()) {
+        // subjectLock.release();
         return false;
       }
-      tl.release();
+      clearLock();
       return true;
     }
     return false;
@@ -51,7 +57,7 @@ public class FileWatcher {
   /**
    * Detect changes in file state and release of any
    * lock in place during change.
-   * @return true if file state has changed
+   * @return true if file state has changed. Leaves lock in subjectLock (ready to be passed to caller)
    */
   private boolean check() {
     if (subject != null) {
@@ -87,6 +93,7 @@ public class FileWatcher {
     }
     return false;
   }
+  
   public void setState() {
     if (subject!=null) {
       lastStat = getStat(subject);
@@ -95,13 +102,41 @@ public class FileWatcher {
     }
   }
   
+  /**
+   * Make a watcher for a particular file. If the file doesn't exist, the
+   * watcher will watch for its creation (and indicate a change of state) 
+   * For locked files, the removal of a lock constitutes a change of 
+   * state if the file was modified.
+   * 
+   * @param subject
+   */
+  
   public FileWatcher(File subject) {
     // TODO Auto-generated constructor stub
     this.subject = subject;
     setState();
   }
-
+  /**
+   * Test for change in file state. Only indicates a change 
+   * after any lock on a file has been released.
+   * @return true if file has been modified.
+   */
   public boolean hasChanged() {
-    return check();
+    boolean res = check();
+    clearLock();
+    return res;
+  }
+  /**
+   * passes lock back to caller if hasChanged returned true.
+   * @return
+   */
+  public Lock getChangedState() {
+    boolean res = check();
+    if (res)
+      return subjectLock;
+    else {
+      clearLock();
+      return null;
+    }
   }
 }
index 072a591..a149a16 100644 (file)
@@ -7,6 +7,7 @@ import java.util.Vector;
 import org.vamsas.client.ClientHandle;
 import org.vamsas.client.simpleclient.ClientsFile;
 import org.vamsas.client.simpleclient.FileWatcher;
+import org.vamsas.client.simpleclient.Lock;
 
 public class ClientsFileTest {
   private static Vector commands;
@@ -60,7 +61,7 @@ public class ClientsFileTest {
             ch=new ClientHandle(args[argc], args[argc+1]);
             ch.setClientUrn(args[argc+2]);
             argc+=3;
-            cfhand.removeClient(ch);
+            cfhand.removeClient(ch, null);
             System.out.println("Client removed (apparently)");
             break;
           case 2:
@@ -91,8 +92,10 @@ public class ClientsFileTest {
             // watch
             FileWatcher w=new FileWatcher(cf);
             while (cf.exists()) {
-              if (w.hasChanged()) {
-                ClientHandle[] cl = cfhand.retrieveClientList();
+              // get watcher's lock to ensure state change is fixed for retrieval
+              Lock chlock=w.getChangedState();
+              if (chlock!=null) {
+                ClientHandle[] cl = cfhand.retrieveClientList(chlock);
                 System.out.println("-- Watching "+cf.getName());
                 //while (w.hasChanged())
                 //  ;