--- /dev/null
+package jalview.api;
+
+import java.util.EventListener;
+
+public interface AlignCalcListener extends EventListener
+{
+ default void workerQueued(AlignCalcWorkerI worker) {}
+ default void workerStarted(AlignCalcWorkerI worker) {}
+ default void workerCompleted(AlignCalcWorkerI worker) {}
+ default void workerExceptional(AlignCalcWorkerI worker, Throwable throwable) {}
+}
*
* @param worker
*/
- void notifyStart(AlignCalcWorkerI worker);
+ void notifyStarted(AlignCalcWorkerI worker);
/**
* tell manager that a thread running worker's run() loop is ready to start
*
* @param typeToRemove
*/
- void removeRegisteredWorkersOfClass(
+ void removeWorkersOfClass(
Class<? extends AlignCalcWorkerI> typeToRemove);
/**
--- /dev/null
+package jalview.api;
+
+import java.util.List;
+
+import jalview.datamodel.AlignmentAnnotation;
+
+public interface AlignCalcManagerI2
+{
+ void registerWorker(AlignCalcWorkerI worker);
+ List<AlignCalcWorkerI> getWorkers();
+ List<AlignCalcWorkerI> getWorkersOfClass(Class<? extends AlignCalcWorkerI> cls);
+ void removeWorker(AlignCalcWorkerI worker);
+ void removeWorkerForAnnotation(AlignmentAnnotation annot);
+ void removeWorkersOfClass(Class<? extends AlignCalcWorkerI> cls);
+ void disableWorker(AlignCalcWorkerI worker);
+ void enableWorker(AlignCalcWorkerI worker);
+ boolean isDisabled(AlignCalcWorkerI worker);
+ boolean isWorking(AlignCalcWorkerI worker);
+ boolean isWorkingWithAnnotation(AlignmentAnnotation annot);
+ boolean isWorking();
+ void startWorker(AlignCalcWorkerI worker);
+ void restartWorkers();
+ void cancelWorker(AlignCalcWorkerI worker);
+ void addAlignCalcListener(AlignCalcListener listener);
+ void removeAlignCalcListener(AlignCalcListener listener);
+}
*/
package jalview.api;
+import java.util.concurrent.Callable;
+
import jalview.datamodel.AlignmentAnnotation;
/**
* Interface describing a worker that calculates alignment annotation(s). The
* main (re-)calculation should be performed by the inherited run() method.
*/
-public interface AlignCalcWorkerI extends Runnable
+public interface AlignCalcWorkerI extends Callable<Void>
{
/**
* Answers true if this worker updates the given annotation (regardless of its
* Removes any annotation(s) managed by this worker from the alignment
*/
void removeAnnotation();
-
+
+
+ /**
+ * Default implementation of call which calls run and propagates the
+ * exception.
+ */
+ @Override
+ public default Void call() throws Exception
+ {
+ run();
+ return null;
+ }
+
+ /**
+ * The main calculation happens here
+ */
+ public void run() throws Exception;
+
/**
* Answers true if the worker should be deleted entirely when its annotation
* is deleted from the display, or false if it should continue to run. Some
*
* @return
*/
- AlignCalcManagerI getCalcManager();
+ AlignCalcManagerI2 getCalcManager();
/**
* get the percentage gaps allowed in a conservation calculation
public AlignViewport(AlignmentI al, JalviewLite applet)
{
super(al);
- calculator = new jalview.workers.AlignCalcManager();
+ calculator = new jalview.workers.AlignCalcManager2();
this.applet = applet;
// we always pad gaps
import jalview.analysis.Conservation;
import jalview.analysis.TreeModel;
import jalview.api.AlignCalcManagerI;
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignCalcWorkerI;
import jalview.api.AlignExportSettingsI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.util.MessageManager;
import jalview.viewmodel.styles.ViewStyle;
import jalview.workers.AlignCalcManager;
+import jalview.workers.AlignCalcManager2;
import jalview.workers.ComplementConsensusThread;
import jalview.workers.ConsensusThread;
import jalview.workers.InformationThread;
return strucConsensus;
}
- protected AlignCalcManagerI calculator = new AlignCalcManager();
+ protected AlignCalcManagerI2 calculator = new AlignCalcManager2();
/**
* trigger update of conservation annotation
{
return;
}
- if (calculator.getRegisteredWorkersOfClass(
- jalview.workers.ConservationThread.class) == null)
+ if (calculator.getWorkersOfClass(
+ jalview.workers.ConservationThread.class).isEmpty())
{
calculator.registerWorker(
new jalview.workers.ConservationThread(this, ap));
{
return;
}
- if (calculator
- .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+ if (calculator.getWorkersOfClass(ConsensusThread.class).isEmpty())
{
calculator.registerWorker(new ConsensusThread(this, ap));
}
}
if (doConsensus)
{
- if (calculator.getRegisteredWorkersOfClass(
- ComplementConsensusThread.class) == null)
+ if (calculator.getWorkersOfClass(ComplementConsensusThread.class).isEmpty())
{
- calculator
- .registerWorker(new ComplementConsensusThread(this, ap));
+ calculator.registerWorker(new ComplementConsensusThread(this, ap));
}
}
}
@Override
public void initInformationWorker(final AlignmentViewPanel ap)
{
- if (calculator
- .getRegisteredWorkersOfClass(InformationThread.class) == null)
+ if (calculator.getWorkersOfClass(InformationThread.class).isEmpty())
{
calculator.registerWorker(new InformationThread(this, ap));
}
{
return;
}
- if (calculator.getRegisteredWorkersOfClass(
- StrucConsensusThread.class) == null)
+ if (calculator.getWorkersOfClass(StrucConsensusThread.class).isEmpty())
{
calculator.registerWorker(new StrucConsensusThread(this, ap));
}
{
return false;
}
- if (calculator.workingInvolvedWith(alignmentAnnotation))
+ if (calculator.isWorkingWithAnnotation(alignmentAnnotation))
{
// System.err.println("grey out ("+alignmentAnnotation.label+")");
return true;
}
@Override
- public AlignCalcManagerI getCalcManager()
+ public AlignCalcManagerI2 getCalcManager()
{
return calculator;
}
// TODO: decouple settings setting from calculation when refactoring
// annotation update method from alignframe to viewport
this.showSequenceLogo = showSequenceLogo;
- calculator.updateAnnotationFor(ConsensusThread.class);
- calculator.updateAnnotationFor(ComplementConsensusThread.class);
- calculator.updateAnnotationFor(StrucConsensusThread.class);
+ for (AlignCalcWorkerI worker : calculator.getWorkers())
+ {
+ if (worker.getClass().equals(ConsensusThread.class) ||
+ worker.getClass().equals(ComplementConsensusThread.class) ||
+ worker.getClass().equals(StrucConsensusThread.class))
+ {
+ worker.updateAnnotation();
+ }
+ }
}
this.showSequenceLogo = showSequenceLogo;
}
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
/*
* list of registered workers
*/
- private volatile List<AlignCalcWorkerI> restartable;
+ private final List<AlignCalcWorkerI> restartable = Collections
+ .synchronizedList(new ArrayList<AlignCalcWorkerI>());
/*
* types of worker _not_ to run (for example, because they have
* previously thrown errors)
*/
- private volatile List<Class<? extends AlignCalcWorkerI>> blackList;
+ private final List<Class<? extends AlignCalcWorkerI>> blackList = Collections
+ .synchronizedList(new ArrayList<Class<? extends AlignCalcWorkerI>>());
/*
* global record of calculations in progress
*/
- private volatile List<AlignCalcWorkerI> inProgress;
+ private final List<AlignCalcWorkerI> inProgress = Collections
+ .synchronizedList(new ArrayList<AlignCalcWorkerI>());
/*
* record of calculations pending or in progress in the current context
*/
- private volatile Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating;
+ private final Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating =
+ new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>();
/*
* workers that have run to completion so are candidates for visual-only
* update of their results
*/
- private HashSet<AlignCalcWorkerI> canUpdate;
-
- /**
- * Constructor
- */
- public AlignCalcManager()
- {
- restartable = Collections
- .synchronizedList(new ArrayList<AlignCalcWorkerI>());
- blackList = Collections.synchronizedList(
- new ArrayList<Class<? extends AlignCalcWorkerI>>());
- inProgress = Collections
- .synchronizedList(new ArrayList<AlignCalcWorkerI>());
- updating = Collections.synchronizedMap(
- new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
- canUpdate = new HashSet<>();
- }
+ private HashSet<AlignCalcWorkerI> canUpdate = new HashSet<>();;
private static boolean listContains(List<AlignCalcWorkerI> upd,
AlignCalcWorkerI worker)
return false;
}
@Override
- public void notifyStart(AlignCalcWorkerI worker)
+ public void notifyStarted(AlignCalcWorkerI worker)
{
synchronized (updating)
{
@Override
public boolean isPending(AlignCalcWorkerI workingClass)
{
- List<AlignCalcWorkerI> upd;
synchronized (updating)
{
- upd = updating.get(workingClass.getClass());
- if (upd == null)
- {
- return false;
- }
- synchronized (upd)
- {
- if (upd.size() > 1)
- {
- return true;
- }
- }
- return false;
+ List<AlignCalcWorkerI> upd = updating.get(workingClass.getClass());
+ return upd != null && upd.size() > 1;
}
}
{
if (!isDisabled(worker))
{
- Thread tw = new Thread(worker);
+ Thread tw = new Thread(() -> {
+ try
+ {
+ worker.run();
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ });
tw.setName(worker.getClass().toString());
tw.start();
}
}
@Override
- public void removeRegisteredWorkersOfClass(
+ public void removeWorkersOfClass(
Class<? extends AlignCalcWorkerI> typeToRemove)
{
List<AlignCalcWorkerI> removable = new ArrayList<>();
--- /dev/null
+package jalview.workers;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+import jalview.api.AlignCalcListener;
+import jalview.api.AlignCalcManagerI;
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignCalcWorkerI;
+import jalview.datamodel.AlignmentAnnotation;
+
+import static java.util.Collections.synchronizedList;
+import static java.util.Collections.synchronizedSet;
+import static java.util.Collections.unmodifiableList;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+public class AlignCalcManager2 implements AlignCalcManagerI2
+{
+ class AlignCalcTask extends FutureTask<Void>
+ {
+ final AlignCalcWorkerI worker;
+
+ public AlignCalcTask(AlignCalcWorkerI worker)
+ {
+ super(new Callable<Void>() {
+ public Void call() throws Exception {
+ notifyStarted(worker);
+ worker.run();
+ return null;
+ }
+ });
+ this.worker = worker;
+ }
+
+ public AlignCalcWorkerI getWorker()
+ {
+ return worker;
+ }
+
+ @Override
+ protected void done()
+ {
+ boolean success = false;
+ Throwable exception = null;
+ try
+ {
+ get();
+ success = true;
+ } catch (ExecutionException e)
+ {
+ exception = e.getCause();
+ if (exception instanceof OutOfMemoryError) {
+ disableWorker(getWorker());
+ }
+ } catch (Throwable e)
+ {
+ exception = e;
+ }
+ finally {
+ inProgress.remove(getWorker());
+ tasks.remove(this);
+ }
+ if (success)
+ notifyCompleted(worker);
+ else
+ notifyExceptional(worker, exception);
+ }
+ }
+
+ // main executor for running workers one-by-one
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ private final List<AlignCalcListener> listeners = new CopyOnWriteArrayList<AlignCalcListener>();
+
+ // list of all registered workers (other collections are subsets of this)
+ private final List<AlignCalcWorkerI> registered = synchronizedList(new ArrayList<>());
+
+ // list of tasks holding queued and running workers
+ private final List<AlignCalcTask> tasks = synchronizedList(new ArrayList<>());
+
+ // the collection of currently running workers
+ private final Set<AlignCalcWorkerI> inProgress = synchronizedSet(new HashSet<>());
+
+ // the collection of workers that will not be started
+ private final Set<AlignCalcWorkerI> disabled = synchronizedSet(new HashSet<>());
+
+ /*
+ * Register the worker with this manager and scheduler for execution.
+ */
+ @Override
+ public void registerWorker(AlignCalcWorkerI worker)
+ {
+ synchronized (registered)
+ {
+ if (!registered.contains(worker))
+ registered.add(worker);
+ }
+ startWorker(worker);
+ }
+
+ @Override
+ public List<AlignCalcWorkerI> getWorkers()
+ {
+ return unmodifiableList(new ArrayList<>(registered));
+ }
+
+ @Override
+ public List<AlignCalcWorkerI> getWorkersOfClass(
+ Class<? extends AlignCalcWorkerI> cls)
+ {
+ synchronized (registered)
+ {
+ return registered.stream()
+ .filter(worker -> worker.getClass().equals(cls))
+ .collect(Collectors.toUnmodifiableList());
+ }
+ }
+
+ @Override
+ public void removeWorker(AlignCalcWorkerI worker)
+ {
+ registered.remove(worker);
+ disabled.remove(worker);
+ }
+
+ @Override
+ public void removeWorkersOfClass(Class<? extends AlignCalcWorkerI> cls)
+ {
+ synchronized (registered)
+ {
+ for (var it = registered.iterator(); it.hasNext();)
+ {
+ var worker = it.next();
+ if (worker.getClass().equals(cls))
+ {
+ it.remove();
+ disabled.remove(worker);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeWorkerForAnnotation(AlignmentAnnotation annot)
+ {
+ synchronized (registered)
+ {
+ for (var it = registered.iterator(); it.hasNext();)
+ {
+ var worker = it.next();
+ if (worker.involves(annot) && worker.isDeletable())
+ {
+ it.remove();
+ disabled.remove(worker);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void disableWorker(AlignCalcWorkerI worker)
+ {
+ assert registered.contains(worker);
+ disabled.add(worker);
+ }
+
+ @Override
+ public void enableWorker(AlignCalcWorkerI worker)
+ {
+ disabled.remove(worker);
+ }
+
+ @Override
+ public void restartWorkers()
+ {
+ synchronized (registered)
+ {
+ for (AlignCalcWorkerI worker : registered)
+ {
+ if (!isDisabled(worker))
+ startWorker(worker);
+ }
+ }
+ }
+
+ @Override
+ public void startWorker(AlignCalcWorkerI worker)
+ {
+ assert registered.contains(worker);
+ synchronized (tasks) {
+ for (var task : tasks)
+ {
+ if (task.getWorker().equals(worker))
+ task.cancel(true);
+ }
+ }
+ AlignCalcTask newTask = new AlignCalcTask(worker);
+ tasks.add(newTask);
+ notifyQueued(worker);
+ executor.execute(newTask);
+ }
+
+ @Override
+ public void cancelWorker(AlignCalcWorkerI worker)
+ {
+ if (isWorking(worker))
+ {
+ synchronized (tasks)
+ {
+ for (var task : tasks)
+ {
+ if (task.getWorker().equals(worker))
+ task.cancel(true);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isDisabled(AlignCalcWorkerI worker)
+ {
+ return disabled.contains(worker);
+ }
+
+ @Override
+ public boolean isWorking(AlignCalcWorkerI worker)
+ {
+ return inProgress.contains(worker);
+ }
+
+ @Override
+ public boolean isWorking()
+ {
+ return !inProgress.isEmpty();
+ }
+
+ @Override
+ public boolean isWorkingWithAnnotation(AlignmentAnnotation annot)
+ {
+ synchronized (inProgress)
+ {
+ for (AlignCalcWorkerI worker : inProgress)
+ {
+ if (worker.involves(annot))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void notifyQueued(AlignCalcWorkerI worker)
+ {
+ for (AlignCalcListener listener : listeners)
+ {
+ listener.workerQueued(worker);
+ }
+ }
+
+ private void notifyStarted(AlignCalcWorkerI worker)
+ {
+ for (AlignCalcListener listener : listeners)
+ {
+ listener.workerStarted(worker);
+ }
+ }
+
+ private void notifyCompleted(AlignCalcWorkerI worker)
+ {
+ for (AlignCalcListener listener : listeners)
+ {
+ try {
+ listener.workerCompleted(worker);
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void notifyExceptional(AlignCalcWorkerI worker,
+ Throwable throwable)
+ {
+ for (AlignCalcListener listener : listeners)
+ {
+ try {
+ listener.workerExceptional(worker, throwable);
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void addAlignCalcListener(AlignCalcListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeAlignCalcListener(AlignCalcListener listener)
+ {
+ listeners.remove(listener);
+ }
+
+}
package jalview.workers;
import jalview.api.AlignCalcManagerI;
+import jalview.api.AlignCalcManagerI2;
import jalview.api.AlignCalcWorkerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
*/
protected AlignViewportI alignViewport;
- protected AlignCalcManagerI calcMan;
+ protected AlignCalcManagerI2 calcMan;
protected AlignmentViewPanel ap;
{
if (calcMan != null)
{
- calcMan.workerComplete(this);
+ calcMan.cancelWorker(this);
+ calcMan.removeWorker(this);
}
alignViewport = null;
calcMan = null;
@Override
public void run()
{
- try
+ if (alignViewport.isClosed())
{
- calcMan.notifyStart(this);
-
- while (!calcMan.notifyWorking(this))
- {
- try
- {
- Thread.sleep(200);
- } catch (InterruptedException ex)
- {
- ex.printStackTrace();
- }
- }
- if (alignViewport.isClosed())
- {
- abortAndDestroy();
- return;
- }
+ abortAndDestroy();
+ return;
+ }
- // removeAnnotation();
+ // removeAnnotation();
AlignmentI alignment = alignViewport.getAlignment();
- if (alignment != null)
+ if (alignment != null)
+ {
+ try
{
- try
+ List<AlignmentAnnotation> anns = counter.calculateAnnotation(
+ alignment, new FeatureRenderer(alignViewport));
+ for (AlignmentAnnotation ann : anns)
{
- List<AlignmentAnnotation> anns = counter.calculateAnnotation(
- alignment, new FeatureRenderer(alignViewport));
- for (AlignmentAnnotation ann : anns)
+ AlignmentAnnotation theAnn = alignment.findOrCreateAnnotation(
+ ann.label, ann.description, false, null, null);
+ theAnn.showAllColLabels = true;
+ theAnn.graph = AlignmentAnnotation.BAR_GRAPH;
+ theAnn.scaleColLabel = true;
+ theAnn.annotations = ann.annotations;
+ setGraphMinMax(theAnn, theAnn.annotations);
+ theAnn.validateRangeAndDisplay();
+ if (!ourAnnots.contains(theAnn))
{
- AlignmentAnnotation theAnn = alignment.findOrCreateAnnotation(
- ann.label, ann.description, false, null, null);
- theAnn.showAllColLabels = true;
- theAnn.graph = AlignmentAnnotation.BAR_GRAPH;
- theAnn.scaleColLabel = true;
- theAnn.annotations = ann.annotations;
- setGraphMinMax(theAnn, theAnn.annotations);
- theAnn.validateRangeAndDisplay();
- if (!ourAnnots.contains(theAnn))
- {
- ourAnnots.add(theAnn);
- }
- // alignment.addAnnotation(ann);
+ ourAnnots.add(theAnn);
}
- } catch (IndexOutOfBoundsException x)
- {
- // probable race condition. just finish and return without any fuss.
- return;
+ // alignment.addAnnotation(ann);
}
+ } catch (IndexOutOfBoundsException x)
+ {
+ // probable race condition. just finish and return without any fuss.
+ return;
}
- } catch (OutOfMemoryError error)
- {
- ap.raiseOOMWarning("calculating annotations", error);
- calcMan.disableWorker(this);
- } finally
- {
- calcMan.workerComplete(this);
}
if (ap != null)
public void run()
{
boolean annotationAdded = false;
- try
+ if (alignViewport.isClosed())
{
- calcMan.notifyStart(this);
+ abortAndDestroy();
+ return;
+ }
- while (!calcMan.notifyWorking(this))
+ if (alignViewport.getAlignment() != null)
+ {
+ try
{
- try
- {
- Thread.sleep(200);
- } catch (InterruptedException ex)
- {
- ex.printStackTrace();
- }
- }
- if (alignViewport.isClosed())
+ annotationAdded = computeAnnotations();
+ } catch (IndexOutOfBoundsException x)
{
- abortAndDestroy();
+ // probable race condition. just finish and return without any fuss.
return;
}
-
- if (alignViewport.getAlignment() != null)
- {
- try
- {
- annotationAdded = computeAnnotations();
- } catch (IndexOutOfBoundsException x)
- {
- // probable race condition. just finish and return without any fuss.
- return;
- }
- }
- } catch (OutOfMemoryError error)
- {
- ap.raiseOOMWarning("calculating feature counts", error);
- calcMan.disableWorker(this);
- } finally
- {
- calcMan.workerComplete(this);
}
if (ap != null)
@Override
public void run()
{
- if (calcMan.isPending(this))
+ AlignmentAnnotation consensus = getConsensusAnnotation();
+ AlignmentAnnotation gap = getGapAnnotation();
+ if ((consensus == null && gap == null))
{
return;
}
- calcMan.notifyStart(this);
- // long started = System.currentTimeMillis();
- try
+ if (alignViewport.isClosed())
{
- AlignmentAnnotation consensus = getConsensusAnnotation();
- AlignmentAnnotation gap = getGapAnnotation();
- if ((consensus == null && gap == null) || calcMan.isPending(this))
- {
- calcMan.workerComplete(this);
- return;
- }
- while (!calcMan.notifyWorking(this))
- {
- // System.err.println("Thread
- // (Consensus"+Thread.currentThread().getName()+") Waiting around.");
- try
- {
- if (ap != null)
- {
- ap.paintAlignment(false, false);
- }
- Thread.sleep(200);
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- if (alignViewport.isClosed())
- {
- abortAndDestroy();
- return;
- }
- AlignmentI alignment = alignViewport.getAlignment();
+ abortAndDestroy();
+ return;
+ }
+ AlignmentI alignment = alignViewport.getAlignment();
- int aWidth = -1;
+ int aWidth = -1;
- if (alignment == null || (aWidth = alignment.getWidth()) < 0)
- {
- calcMan.workerComplete(this);
- return;
- }
+ if (alignment == null || (aWidth = alignment.getWidth()) < 0)
+ {
+ return;
+ }
- eraseConsensus(aWidth);
- computeConsensus(alignment);
- updateResultAnnotation(true);
+ eraseConsensus(aWidth);
+ computeConsensus(alignment);
+ updateResultAnnotation(true);
- if (ap != null)
- {
- ap.paintAlignment(true, true);
- }
- } catch (OutOfMemoryError error)
- {
- calcMan.disableWorker(this);
- ap.raiseOOMWarning("calculating consensus", error);
- } finally
+ if (ap != null)
{
- /*
- * e.g. ArrayIndexOutOfBoundsException can happen due to a race condition
- * - alignment was edited at same time as calculation was running
- */
- calcMan.workerComplete(this);
+ ap.paintAlignment(true, true);
}
}
@Override
public void run()
{
- try
+ if ((alignViewport == null) || (calcMan == null)
+ || (alignViewport.isClosed()))
{
- calcMan.notifyStart(this); // updatingConservation = true;
-
- while ((calcMan != null) && (!calcMan.notifyWorking(this)))
- {
- try
- {
- if (ap != null)
- {
- // ap.paintAlignment(false);
- }
- Thread.sleep(200);
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- if ((alignViewport == null) || (calcMan == null)
- || (alignViewport.isClosed()))
- {
- abortAndDestroy();
- return;
- }
- List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
- AlignmentI alignment = alignViewport.getAlignment();
- conservation = alignViewport.getAlignmentConservationAnnotation();
- quality = alignViewport.getAlignmentQualityAnnot();
- ourAnnot.add(conservation);
- ourAnnot.add(quality);
- ourAnnots = ourAnnot;
- ConsPercGaps = alignViewport.getConsPercGaps();
- // AlignViewport.UPDATING_CONSERVATION = true;
-
- if (alignment == null || (alWidth = alignment.getWidth()) < 0)
- {
- calcMan.workerComplete(this);
- // .updatingConservation = false;
- // AlignViewport.UPDATING_CONSERVATION = false;
+ abortAndDestroy();
+ return;
+ }
+ List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
+ AlignmentI alignment = alignViewport.getAlignment();
+ conservation = alignViewport.getAlignmentConservationAnnotation();
+ quality = alignViewport.getAlignmentQualityAnnot();
+ ourAnnot.add(conservation);
+ ourAnnot.add(quality);
+ ourAnnots = ourAnnot;
+ ConsPercGaps = alignViewport.getConsPercGaps();
+ // AlignViewport.UPDATING_CONSERVATION = true;
- return;
- }
- try
- {
- cons = Conservation.calculateConservation("All",
- alignment.getSequences(), 0, alWidth - 1, false,
- ConsPercGaps, quality != null);
- } catch (IndexOutOfBoundsException x)
- {
- // probable race condition. just finish and return without any fuss.
- calcMan.workerComplete(this);
- return;
- }
- updateResultAnnotation(true);
- } catch (OutOfMemoryError error)
+ if (alignment == null || (alWidth = alignment.getWidth()) < 0)
{
- ap.raiseOOMWarning("calculating conservation", error);
- calcMan.disableWorker(this);
- // alignViewport.conservation = null;
- // this.alignViewport.quality = null;
-
+ // .updatingConservation = false;
+ // AlignViewport.UPDATING_CONSERVATION = false;
+ return;
+ }
+ try
+ {
+ cons = Conservation.calculateConservation("All",
+ alignment.getSequences(), 0, alWidth - 1, false,
+ ConsPercGaps, quality != null);
+ } catch (IndexOutOfBoundsException x)
+ {
+ // probable race condition. just finish and return without any fuss.
+ return;
}
- calcMan.workerComplete(this);
+ updateResultAnnotation(true);
if ((alignViewport == null) || (calcMan == null)
|| (alignViewport.isClosed()))
{
return;
}
- if (calcMan.isPending(this))
+ if (alignViewport.isClosed())
{
+ abortAndDestroy();
return;
}
- calcMan.notifyStart(this);
- // long started = System.currentTimeMillis();
- try
+ AlignmentI alignment = alignViewport.getAlignment();
+ int aWidth = alignment == null ? -1 : alignment.getWidth();
+ if (aWidth < 0)
{
- if (calcMan.isPending(this))
- {
- // another instance of this is waiting to run
- calcMan.workerComplete(this);
- return;
- }
- while (!calcMan.notifyWorking(this))
- {
- // another thread in progress, wait my turn
- try
- {
- if (ap != null)
- {
- ap.paintAlignment(false, false);
- }
- Thread.sleep(200);
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- if (alignViewport.isClosed())
- {
- abortAndDestroy();
- return;
- }
-
- AlignmentI alignment = alignViewport.getAlignment();
- int aWidth = alignment == null ? -1 : alignment.getWidth();
- if (aWidth < 0)
- {
- calcMan.workerComplete(this);
- return;
- }
+ return;
+ }
- /*
- * compute information profiles for any HMM consensus sequences
- * for the alignment or sub-groups
- */
- computeProfiles(alignment);
+ /*
+ * compute information profiles for any HMM consensus sequences
+ * for the alignment or sub-groups
+ */
+ computeProfiles(alignment);
- /*
- * construct the corresponding annotations
- */
- updateAnnotation();
+ /*
+ * construct the corresponding annotations
+ */
+ updateAnnotation();
- if (ap != null)
- {
- ap.adjustAnnotationHeight();
- ap.paintAlignment(true, true);
- }
- } catch (OutOfMemoryError error)
- {
- calcMan.disableWorker(this);
- ap.raiseOOMWarning("calculating information", error);
- } finally
+ if (ap != null)
{
- calcMan.workerComplete(this);
+ ap.adjustAnnotationHeight();
+ ap.paintAlignment(true, true);
}
}
@Override
public void run()
{
- try
- {
- if (calcMan.isPending(this))
- {
- return;
- }
- calcMan.notifyStart(this);
- while (!calcMan.notifyWorking(this))
- {
- try
- {
- if (ap != null)
- {
- // ap.paintAlignment(false);
- }
-
- Thread.sleep(200);
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
if (alignViewport.isClosed())
{
abortAndDestroy();
if (alignment == null || (aWidth = alignment.getWidth()) < 0)
{
- calcMan.workerComplete(this);
return;
}
strucConsensus = alignViewport.getAlignmentStrucConsensusAnnotation();
if (rnaStruc == null || !rnaStruc.isValidStruc())
{
- calcMan.workerComplete(this);
return;
}
alignment.getWidth(), hStrucConsensus, true, rnaStruc);
} catch (ArrayIndexOutOfBoundsException x)
{
- calcMan.workerComplete(this);
return;
}
alignViewport.setRnaStructureConsensusHash(hStrucConsensus);
// TODO AlignmentAnnotation rnaStruc!!!
updateResultAnnotation(true);
- } catch (OutOfMemoryError error)
- {
- calcMan.disableWorker(this);
-
- // consensus = null;
- // hconsensus = null;
- ap.raiseOOMWarning("calculating RNA structure consensus", error);
- } finally
- {
- calcMan.workerComplete(this);
- if (ap != null)
- {
- ap.paintAlignment(true, true);
- }
- }
}
{
List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
.getCalcManager()
- .getRegisteredWorkersOfClass(aaui.getClient());
+ .getWorkersOfClass(aaui.getClient());
if (aaconClient != null && aaconClient.size() > 0)
{
SeqAnnotationServiceCalcWorker worker = (SeqAnnotationServiceCalcWorker) aaconClient
{
List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
- .getCalcManager().getRegisteredWorkersOfClass(
- SeqAnnotationServiceCalcWorker.class);
+ .getCalcManager()
+ .getWorkersOfClass(SeqAnnotationServiceCalcWorker.class);
if (aaconClient != null)
{
for (AlignCalcWorkerI worker : aaconClient)
return;
}
List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
- .getCalcManager().getRegisteredWorkersOfClass(
- SeqAnnotationServiceCalcWorker.class);
+ .getCalcManager()
+ .getWorkersOfClass(SeqAnnotationServiceCalcWorker.class);
boolean serviceEnabled = false;
if (aaconClient != null)
AlignFrame alignFrame)
{
alignFrame.getViewport().getCalcManager()
- .removeRegisteredWorkersOfClass(aaui.getClient());
+ .removeWorkersOfClass(aaui.getClient());
}
}
\ No newline at end of file
private int min_valid_seqs;
@Override
- public void run()
+ public void run() throws Exception
{
- if (checkDone())
+ if (alignViewport.isClosed())
{
+ abortAndDestroy();
return;
}
if (!hasService())
{
- calcMan.workerComplete(this);
return;
}
{
jalview.bin.Cache.log.debug(
"Sequences for analysis service were null or not valid");
- calcMan.workerComplete(this);
return;
}
Cache.log.debug("Status now " + running.getState());
}
- if (calcMan.isPending(this) && isInteractiveUpdate())
- {
- Cache.log.debug("Analysis service job is stale. aborting.");
- // job has become stale.
- if (!finished) {
- finished = true;
- // cancel this job and yield to the new job
- try
- {
- if (cancellable
- && ((CancellableI) annotService).cancel(running))
- {
- System.err.println("Cancelled job: " + rslt);
- }
- else
- {
- System.err.println("FAILED TO CANCEL job: " + rslt);
- }
-
- } catch (Exception x)
- {
-
- }
- }
- rslt = running.getJobHandle();
- return;
- }
-
// pull any stats - some services need to flush log output before
// results are available
Cache.log.debug("Updating progress log for annotation service.");
try
{
- annotService.updateJobProgress(running);
+ annotService.updateJobProgress(running);
} catch (Throwable thr)
{
Cache.log.debug("Ignoring exception during progress update.",
System.err
.println("Blacklisting worker due to unexpected exception:");
x.printStackTrace();
+ throw new Exception(x);
} finally
{
- calcMan.workerComplete(this);
if (ap != null)
{
if (guiProgress != null && progressId != -1)
}
}
- /**
- * notify manager that we have started, and wait for a free calculation slot
- *
- * @return true if slot is obtained and work still valid, false if another
- * thread has done our work for us.
- */
- protected boolean checkDone()
- {
- calcMan.notifyStart(this);
- ap.paintAlignment(false, false);
- while (!calcMan.notifyWorking(this))
- {
- if (calcMan.isWorking(this))
- {
- return true;
- }
- try
- {
- if (ap != null)
- {
- ap.paintAlignment(false, false);
- }
-
- Thread.sleep(200);
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- if (alignViewport.isClosed())
- {
- abortAndDestroy();
- return true;
- }
- return false;
- }
-
protected void updateOurAnnots(List<AlignmentAnnotation> ourAnnot)
{
List<AlignmentAnnotation> our = ourAnnots;
List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
.getCalcManager()
- .getRegisteredWorkersOfClass(SeqAnnotationServiceCalcWorker.class);
+ .getWorkersOfClass(SeqAnnotationServiceCalcWorker.class);
SeqAnnotationServiceCalcWorker worker = null;
if (clnts != null)
import static org.testng.AssertJUnit.assertTrue;
import jalview.api.AlignCalcManagerI;
+import jalview.api.AlignCalcManagerI2;
import jalview.api.AlignCalcWorkerI;
import jalview.api.FeatureRenderer;
import jalview.datamodel.Alignment;
@Test(groups = "Functional")
public void testRemoveWorkerForAnnotation()
{
- AlignCalcManagerI acm = alignFrame.getViewport().getCalcManager();
+ AlignCalcManagerI2 acm = alignFrame.getViewport().getCalcManager();
final AlignmentAnnotation ann1 = new AlignmentAnnotation("Ann1",
"desc", new Annotation[] {});
final AlignmentAnnotation ann2 = new AlignmentAnnotation("Ann2",
}
}
- List<AlignCalcWorkerI> workers = acm
- .getRegisteredWorkersOfClass(worker1.getClass());
+ List<AlignCalcWorkerI> workers = acm.getWorkersOfClass(worker1.getClass());
assertEquals(2, workers.size());
assertTrue(workers.contains(worker1));
assertTrue(workers.contains(worker2));
* remove workers for ann2 (there aren't any)
*/
acm.removeWorkerForAnnotation(ann2);
- assertTrue(acm.getRegisteredWorkersOfClass(worker1.getClass())
- .contains(worker1));
- assertTrue(acm.getRegisteredWorkersOfClass(worker1.getClass())
- .contains(worker2));
+ assertTrue(acm.getWorkersOfClass(worker1.getClass()).contains(worker1));
+ assertTrue(acm.getWorkersOfClass(worker1.getClass()).contains(worker2));
assertFalse(acm.isDisabled(worker1));
assertFalse(acm.isDisabled(worker2));
* - should delete worker1 but not worker2
*/
acm.removeWorkerForAnnotation(ann1);
- assertEquals(1, acm.getRegisteredWorkersOfClass(worker1.getClass())
- .size());
- assertTrue(acm.getRegisteredWorkersOfClass(worker1.getClass())
- .contains(worker2));
+ assertEquals(1, acm.getWorkersOfClass(worker1.getClass()).size());
+ assertTrue(acm.getWorkersOfClass(worker1.getClass()).contains(worker2));
assertFalse(acm.isDisabled(worker1));
assertFalse(acm.isDisabled(worker2));
}