formal polling thread for particular FileWatcher types (VamsasFile or SessionFile...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 12 Jan 2007 15:38:15 +0000 (15:38 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 12 Jan 2007 15:38:15 +0000 (15:38 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@336 be28352e-c001-0410-b1a7-c7978e42abec

src/uk/ac/vamsas/client/simpleclient/SessionFileWatcherElement.java [new file with mode: 0644]
src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherElement.java [new file with mode: 0644]
src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherThread.java [new file with mode: 0644]
src/uk/ac/vamsas/client/simpleclient/WatcherCallBack.java [new file with mode: 0644]
src/uk/ac/vamsas/client/simpleclient/WatcherElement.java [new file with mode: 0644]

diff --git a/src/uk/ac/vamsas/client/simpleclient/SessionFileWatcherElement.java b/src/uk/ac/vamsas/client/simpleclient/SessionFileWatcherElement.java
new file mode 100644 (file)
index 0000000..034aae6
--- /dev/null
@@ -0,0 +1,56 @@
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+\r
+/**\r
+ * Element of the VamsasFileWatcherThread event generator chain.\r
+ * Keep a reference to this element before adding it to the chain \r
+ * in order to control the generation of events with halt and enable.\r
+ * \r
+ * doWatch will do nothing if the element is not enabled.\r
+ * \r
+ */\r
+public class SessionFileWatcherElement extends WatcherElement {\r
+  SessionFile watched=null;\r
+  /**\r
+   * create a new, enabled watch element\r
+   * @param watcher file being watched\r
+   * @param handler handler to call on state change\r
+   */\r
+  public SessionFileWatcherElement(SessionFile watcher, WatcherCallBack handler) {\r
+    this(watcher, handler, true);\r
+  }\r
+  protected void initWatch() {\r
+    if (watched==null)\r
+      return;\r
+    if (watcher==null || !watcher.getSubject().equals(watched.sessionFile)) \r
+      watcher=new FileWatcher(watched.sessionFile);\r
+    else\r
+      watcher.setState();\r
+  }\r
+  protected void endWatch() {\r
+    // leaves watcher in state its in.\r
+  }\r
+  /**\r
+   * new watcher with flag to initially skip watching this sessionfile\r
+   * @param watcher\r
+   * @param handler\r
+   * @param enableWatching\r
+   */\r
+  public SessionFileWatcherElement(SessionFile watcher, WatcherCallBack handler, boolean enableWatching) {\r
+    super(handler);\r
+    this.watched = watcher;\r
+    if (enableWatching)\r
+      enableWatch();\r
+    else\r
+      haltWatch();\r
+  }\r
+  /**\r
+   * @return the watched\r
+   */\r
+  public SessionFile getWatched() {\r
+    return watched;\r
+  }\r
+  protected String getSubject() {\r
+    return watched.sessionFile.toString();\r
+  }\r
+}\r
diff --git a/src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherElement.java b/src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherElement.java
new file mode 100644 (file)
index 0000000..ceb1e65
--- /dev/null
@@ -0,0 +1,54 @@
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+\r
+/**\r
+ * Element of the VamsasFileWatcherThread event generator chain.\r
+ * Keep a reference to this element before adding it to the chain \r
+ * in order to control the generation of events with halt and enable.\r
+ * \r
+ * doWatch will do nothing if the element is not enabled.\r
+ * \r
+ */\r
+public class VamsasFileWatcherElement extends WatcherElement {\r
+  VamsasFile watched=null;\r
+  /**\r
+   * create a new, enabled watch element\r
+   * @param watcher file being watched\r
+   * @param handler handler to call on state change\r
+   */\r
+  public VamsasFileWatcherElement(VamsasFile watcher, WatcherCallBack handler) {\r
+    this(watcher, handler, true);\r
+  }\r
+  protected void initWatch() {\r
+    if (watched==null)\r
+      return;\r
+    watched.unLock(); // very very essential!\r
+    watcher = new FileWatcher(watched.getVamsasFile());\r
+  }\r
+  protected void endWatch() {\r
+    // leaves watcher in state its in.\r
+  }\r
+  /**\r
+   * new watcher with flag to initially skip watching this sessionfile\r
+   * @param watcher\r
+   * @param handler\r
+   * @param enableWatching\r
+   */\r
+  public VamsasFileWatcherElement(VamsasFile watcher, WatcherCallBack handler, boolean enableWatching) {\r
+    super(handler);\r
+    this.watched = watcher;\r
+    if (enableWatching)\r
+      enableWatch();\r
+    else\r
+      haltWatch();\r
+  }\r
+  /**\r
+   * @return the watched\r
+   */\r
+  public VamsasFile getWatched() {\r
+    return watched;\r
+  }\r
+  protected String getSubject() {\r
+    return watched.getVamsasFile().toString();\r
+  }\r
+}\r
diff --git a/src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherThread.java b/src/uk/ac/vamsas/client/simpleclient/VamsasFileWatcherThread.java
new file mode 100644 (file)
index 0000000..f0af3d4
--- /dev/null
@@ -0,0 +1,92 @@
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+import java.util.Iterator;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+/**\r
+ * Watches a bunch of VamsasFile states, calling \r
+ * the associated event handler when anything changes.\r
+ * @author JimP\r
+ *\r
+ */\r
+public class VamsasFileWatcherThread extends Thread {\r
+  private Log log = LogFactory.getLog(VamsasFileWatcherThread.class);  \r
+  /* (non-Javadoc)\r
+   * @see java.lang.Thread#run()\r
+   */\r
+  EventGeneratorThread client=null;\r
+  private Vector elements=null;\r
+  public VamsasFileWatcherThread(EventGeneratorThread client) {\r
+    this.client = client;\r
+    elements=new Vector();\r
+  }\r
+  public void addElement(WatcherElement welement) {\r
+    elements.addElement(welement);\r
+  }\r
+  public void removeElemenet(WatcherElement welement) {\r
+    elements.removeElement(welement);\r
+  }\r
+  public void clearElements() {\r
+    elements.clear();\r
+  }\r
+  /**\r
+   * true if the thread is running\r
+   */\r
+  boolean running=false;\r
+  /**\r
+   * true if the watcher loop is in progress\r
+   */\r
+  boolean watching=false;\r
+  public void haltWatchers() {\r
+    if (!watching)\r
+      return;\r
+    watching=false;\r
+    // wait arount for WATCH_SLEEP milliseconds before returning\r
+    // in the hope that the watcher loop has stopped\r
+    try {\r
+      long time = System.currentTimeMillis()+WATCH_SLEEP;\r
+      interrupt();\r
+      while (running && time>System.currentTimeMillis()) {\r
+        Thread.sleep(1);\r
+      }\r
+    } catch (Exception e) {};\r
+    if (running)\r
+      log.warn("haltWatchers returning whilst thread is still running.");\r
+  }\r
+  \r
+  /**\r
+   * time between checks for changes of state on the file\r
+   */\r
+  public int WATCH_SLEEP=30; \r
+  /**\r
+   * check each watcher in sequence, monitoring any events generated.\r
+   * Then wait WATCH_SLEEP milliseconds before checking all again (if there were no events)\r
+   */\r
+  public void run() {\r
+    running=true;\r
+    watching=true;\r
+    log.debug("Starting WatcherThread poll loop");\r
+    while (watching) {\r
+      boolean wait=true;\r
+      Iterator watchers=elements.iterator();\r
+      while (watching && watchers.hasNext()) {\r
+        WatcherElement watch = (WatcherElement) watchers.next();\r
+        if (watch.doWatch()) {\r
+          wait=false;\r
+          log.debug("Event generated for watcher on "+watch.getWatcher().getSubject());\r
+        }\r
+      }\r
+      if (watching && wait) {\r
+        try {\r
+          Thread.sleep(WATCH_SLEEP);\r
+        }\r
+        catch (InterruptedException e) {};\r
+      }\r
+    }\r
+    log.debug("Finishing WatcherThread poll loop");\r
+    running=false;\r
+  }\r
+}\r
diff --git a/src/uk/ac/vamsas/client/simpleclient/WatcherCallBack.java b/src/uk/ac/vamsas/client/simpleclient/WatcherCallBack.java
new file mode 100644 (file)
index 0000000..28ff915
--- /dev/null
@@ -0,0 +1,12 @@
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+/**\r
+ * Interface for VamsasFileWatcherElement call back events generated by the VamsasFileWatcherThread.\r
+ */\r
+public interface WatcherCallBack {\r
+  /**\r
+   * \r
+   * @return true to enable watcher, or false to disable it in future WatcherThread cycles.\r
+   */\r
+  public boolean handleWatchEvent(WatcherElement watcher, Lock lock);\r
+}\r
diff --git a/src/uk/ac/vamsas/client/simpleclient/WatcherElement.java b/src/uk/ac/vamsas/client/simpleclient/WatcherElement.java
new file mode 100644 (file)
index 0000000..54a31be
--- /dev/null
@@ -0,0 +1,125 @@
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+\r
+\r
+public abstract class WatcherElement {\r
+\r
+  private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(VamsasFileWatcherElement.class);\r
+  protected FileWatcher watcher = null;\r
+  protected WatcherCallBack handler = null;\r
+  /**\r
+   * set this to false to stop the thread\r
+   */\r
+  private boolean watchForChange = true;\r
+  /**\r
+   * true when the handler is being called for this watcher\r
+   */\r
+  protected boolean handlerCalled = false;\r
+\r
+  public WatcherElement(WatcherCallBack handler) {\r
+    this.handler = handler;\r
+  }\r
+  /**\r
+   * will instruct watcher to stop and wait around for one WATCH_SLEEP\r
+   * before returning. If no thread is running then it returns immediately.\r
+   */\r
+  public void haltWatch() {\r
+    if (log.isDebugEnabled())\r
+      log.debug("haltWatch on "+watcher.getSubject());\r
+    // set the flag to skip this watch element.\r
+    watchForChange=false;\r
+    endWatch();\r
+    // watcher=null;\r
+    \r
+  }\r
+  /**\r
+   * called by haltWatch before \r
+   * clearing the FileWatcher reference.\r
+   *\r
+   */\r
+  protected abstract void endWatch();\r
+  /**\r
+   * called to generate the watcher object\r
+   * by enableWatch and in doWatch\r
+   *\r
+   */\r
+  protected abstract void initWatch();\r
+  /**\r
+   * implemented for debug information purposes.\r
+   * @return Informative string about what the watcher is watching\r
+   */\r
+  protected abstract String getSubject();\r
+  /**\r
+   * must be called by implementations of \r
+   * enablewatch\r
+   */\r
+  protected void enableWatch() {\r
+    watchForChange=true;\r
+    initWatch();\r
+    if (log.isDebugEnabled())\r
+      log.debug("enableWatch returning on "+getSubject());\r
+  }\r
+\r
+  /**\r
+   * Originally from the uk.ac.vamsas.test.simpleclient.ArchiveClient method\r
+   * @return true if the handler was called for a changeEvent\r
+   */\r
+  public boolean doWatch() {\r
+    if (!watchForChange || handler==null)\r
+      return false;\r
+    if (watcher==null)\r
+      initWatch(); // somehow not done the first time\r
+    handlerCalled=false;\r
+    Lock doclock=null;\r
+    try {\r
+      doclock=watcher.getChangedState();\r
+    } catch (Exception e) {\r
+      log.error("Whilst watching "+watcher.getSubject(), e);\r
+    }\r
+    if (doclock==null)\r
+      return false;\r
+    handlerCalled=true;\r
+    if (log.isDebugEnabled())\r
+      log.debug("Triggering watchEvent for change on "+watcher.getSubject());\r
+      boolean finish=!handler.handleWatchEvent(this, doclock);\r
+    doclock=null; // TODO: check that lock should really be released rather than dereferenced\r
+    if (finish)\r
+      haltWatch();\r
+    else\r
+      enableWatch();\r
+    handlerCalled=false;\r
+    return true;\r
+  }\r
+\r
+  /**\r
+   * @return the handler\r
+   */\r
+  public WatcherCallBack getHandler() {\r
+    return handler;\r
+  }\r
+  /**\r
+   * @return the handlerCalled\r
+   */\r
+  public boolean isHandlerCalled() {\r
+    return handlerCalled;\r
+  }\r
+  /**\r
+   * \r
+   * @return true if watcher is enabled\r
+   */\r
+  public boolean isWatchEnabled() {\r
+    return watchForChange;\r
+  }\r
+  /**\r
+   * @param handler the handler to set\r
+   */\r
+  public void setHandler(WatcherCallBack handler) {\r
+    this.handler = handler;\r
+  }\r
+  /**\r
+   * @return the watcher\r
+   */\r
+  public FileWatcher getWatcher() {\r
+    return watcher;\r
+  }\r
+}\r