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