Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.ws

File AWSThread.java

 

Coverage histogram

../../img/srcFileCovDistChart3.png
47% of files have more coverage

Code metrics

38
88
15
1
396
245
42
0.48
5.87
15
2.8

Classes

Class Line # Actions
AWSThread 37 88 42
0.2198581522%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.ws;
22   
23    import jalview.bin.Cache;
24    import jalview.datamodel.AlignedCodonFrame;
25    import jalview.datamodel.Alignment;
26    import jalview.datamodel.AlignmentI;
27    import jalview.datamodel.AlignmentView;
28    import jalview.datamodel.SequenceI;
29    import jalview.gui.AlignFrame;
30    import jalview.gui.WebserviceInfo;
31    import jalview.util.MessageManager;
32    import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
33   
34    import java.util.ArrayList;
35    import java.util.List;
36   
 
37    public abstract class AWSThread extends Thread
38    {
39   
40    /**
41    * view that this job was associated with
42    */
43    protected AlignmentI currentView = null;
44   
45    /**
46    * feature settings from view that job was associated with
47    */
48    protected FeatureRendererSettings featureSettings = null;
49   
50    /**
51    * metadata about this web service
52    */
53    protected WebserviceInfo wsInfo = null;
54   
55    /**
56    * original input data for this job
57    */
58    protected AlignmentView input = null;
59   
60    /**
61    * dataset sequence relationships to be propagated onto new results
62    */
63    protected List<AlignedCodonFrame> codonframe = null;
64   
65    /**
66    * are there jobs still running in this thread.
67    */
68    protected boolean jobComplete = false;
69   
70    /**
71    * one or more jobs being managed by this thread.
72    */
73    protected AWsJob jobs[] = null;
74   
75    /**
76    * full name of service
77    */
78    protected String WebServiceName = null;
79   
80    protected char defGapChar = '-';
81   
82    /**
83    * header prepended to all output from job
84    */
85    protected String OutputHeader;
86   
87    /**
88    * only used when reporting a web service out of memory error - the job ID
89    * will be concatenated to the URL
90    */
91    protected String WsUrl = null;
92   
93    /*
94    * The AlignFrame from which the service was requested.
95    */
96    private AlignFrame alignFrame;
97   
98    /**
99    * generic web service job/subjob poll loop
100    */
 
101  1 toggle @Override
102    public void run()
103    {
104  1 JobStateSummary jstate = null;
105  1 if (jobs == null)
106    {
107  0 jobComplete = true;
108    }
109  1 while (!jobComplete)
110    {
111  1 jstate = new JobStateSummary();
112  1 for (int j = 0; j < jobs.length; j++)
113    {
114   
115  1 if (!jobs[j].submitted && jobs[j].hasValidInput())
116    {
117  1 StartJob(jobs[j]);
118    }
119   
120  1 if (jobs[j].submitted && !jobs[j].subjobComplete)
121    {
122  0 try
123    {
124  0 pollJob(jobs[j]);
125  0 if (!jobs[j].hasResponse())
126    {
127  0 throw (new Exception(
128    "Timed out when communicating with server\nTry again later.\n"));
129    }
130  0 jalview.bin.Cache.log.debug("Job " + j + " Result state "
131    + jobs[j].getState() + "(ServerError="
132    + jobs[j].isServerError() + ")");
133    } catch (Exception ex)
134    {
135    // Deal with Transaction exceptions
136  0 wsInfo.appendProgressText(jobs[j].jobnum, MessageManager
137    .formatMessage("info.server_exception", new Object[]
138    { WebServiceName, ex.getMessage() }));
139    // always output the exception's stack trace to the log
140  0 Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum
141    + ") Server exception.");
142    // todo: could limit trace to cause if this is a SOAPFaultException.
143  0 ex.printStackTrace();
144   
145  0 if (jobs[j].allowedServerExceptions > 0)
146    {
147  0 jobs[j].allowedServerExceptions--;
148  0 Cache.log.debug("Sleeping after a server exception.");
149  0 try
150    {
151  0 Thread.sleep(5000);
152    } catch (InterruptedException ex1)
153    {
154    }
155    }
156    else
157    {
158  0 Cache.log.warn("Dropping job " + j + " " + jobs[j].jobId);
159  0 jobs[j].subjobComplete = true;
160  0 wsInfo.setStatus(jobs[j].jobnum,
161    WebserviceInfo.STATE_STOPPED_SERVERERROR);
162    }
163    } catch (OutOfMemoryError er)
164    {
165  0 jobComplete = true;
166  0 jobs[j].subjobComplete = true;
167  0 jobs[j].clearResponse(); // may contain out of date result data
168  0 wsInfo.setStatus(jobs[j].jobnum,
169    WebserviceInfo.STATE_STOPPED_ERROR);
170  0 Cache.log.error("Out of memory when retrieving Job " + j
171    + " id:" + WsUrl + "/" + jobs[j].jobId, er);
172  0 new jalview.gui.OOMWarning(
173    "retrieving result for " + WebServiceName, er);
174  0 System.gc();
175    }
176    }
177  1 jstate.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
178    }
179    // Decide on overall state based on collected jobs[] states
180  0 updateGlobalStatus(jstate);
181  0 if (!jobComplete)
182    {
183  0 try
184    {
185  0 Thread.sleep(5000);
186    } catch (InterruptedException e)
187    {
188  0 Cache.log.debug("Interrupted sleep waiting for next job poll.",
189    e);
190    }
191    // System.out.println("I'm alive "+alTitle);
192    }
193    }
194  0 if (jobComplete && jobs != null)
195    {
196  0 parseResult(); // tidy up and make results available to user
197    }
198    else
199    {
200  0 Cache.log.debug(
201    "WebServiceJob poll loop finished with no jobs created.");
202  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
203  0 wsInfo.appendProgressText(
204    MessageManager.getString("info.no_jobs_ran"));
205  0 wsInfo.setFinishedNoResults();
206    }
207    }
208   
 
209  0 toggle protected void updateGlobalStatus(JobStateSummary jstate)
210    {
211  0 if (jstate.running > 0)
212    {
213  0 wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
214    }
215  0 else if (jstate.queuing > 0)
216    {
217  0 wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
218    }
219    else
220    {
221  0 jobComplete = true;
222  0 if (jstate.finished > 0)
223    {
224  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
225    }
226  0 else if (jstate.error > 0)
227    {
228  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
229    }
230  0 else if (jstate.serror > 0)
231    {
232  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
233    }
234    }
235    }
236   
 
237  0 toggle public AWSThread()
238    {
239  0 super();
240    }
241   
 
242  0 toggle public AWSThread(Runnable target)
243    {
244  0 super(target);
245    }
246   
 
247  0 toggle public AWSThread(String name)
248    {
249  0 super(name);
250    }
251   
 
252  0 toggle public AWSThread(ThreadGroup group, Runnable target)
253    {
254  0 super(group, target);
255    }
256   
 
257  0 toggle public AWSThread(ThreadGroup group, String name)
258    {
259  0 super(group, name);
260    }
261   
 
262  0 toggle public AWSThread(Runnable target, String name)
263    {
264  0 super(target, name);
265    }
266   
 
267  0 toggle public AWSThread(ThreadGroup group, Runnable target, String name)
268    {
269  0 super(group, target, name);
270    }
271   
272    /**
273    * query web service for status of job. on return, job.result must not be null
274    * - if it is then it will be assumed that the job status query timed out and
275    * a server exception will be logged.
276    *
277    * @param job
278    * @throws Exception
279    * will be logged as a server exception for this job
280    */
281    public abstract void pollJob(AWsJob job) throws Exception;
282   
283    /**
284    * submit job to web service
285    *
286    * @param job
287    */
288    public abstract void StartJob(AWsJob job);
289   
290    /**
291    * process the set of AWsJob objects into a set of results, and tidy up.
292    */
293    public abstract void parseResult();
294   
295    /**
296    * helper function to conserve dataset references to sequence objects returned
297    * from web services 1. Propagates AlCodonFrame data from
298    * <code>codonframe</code> to <code>al</code> TODO: refactor to datamodel
299    *
300    * @param al
301    */
 
302  0 toggle public void propagateDatasetMappings(Alignment al)
303    {
304  0 if (codonframe != null)
305    {
306  0 SequenceI[] alignment = al.getSequencesArray();
307  0 for (int sq = 0; sq < alignment.length; sq++)
308    {
309  0 for (AlignedCodonFrame acf : codonframe)
310    {
311  0 final SequenceI seq = alignment[sq];
312  0 if (acf != null && acf.involvesSequence(seq))
313    {
314  0 al.addCodonFrame(acf);
315  0 break;
316    }
317    }
318    }
319    }
320    }
321   
 
322  0 toggle public AWSThread(ThreadGroup group, Runnable target, String name,
323    long stackSize)
324    {
325  0 super(group, target, name, stackSize);
326    }
327   
328    /**
329    *
330    * @return gap character to use for any alignment generation
331    */
 
332  0 toggle public char getGapChar()
333    {
334  0 return defGapChar;
335    }
336   
337    /**
338    *
339    * @param alignFrame
340    * reference for copying mappings across
341    * @param wsInfo
342    * gui attachment point
343    * @param input
344    * input data for the calculation
345    * @param webServiceName
346    * name of service
347    * @param wsUrl
348    * url of the service being invoked
349    */
 
350  0 toggle public AWSThread(AlignFrame alignFrame, WebserviceInfo wsinfo,
351    AlignmentView input, String webServiceName, String wsUrl)
352    {
353  0 this(alignFrame, wsinfo, input, wsUrl);
354  0 WebServiceName = webServiceName;
355    }
356   
357    /**
358    * Extracts additional info from alignment view's context.
359    *
360    * @param alframe
361    * - reference for copying mappings and display styles across
362    * @param wsinfo2
363    * - gui attachment point - may be null
364    * @param alview
365    * - input data for the calculation
366    * @param wsurl2
367    * - url of the service being invoked
368    */
 
369  2 toggle public AWSThread(AlignFrame alframe, WebserviceInfo wsinfo2,
370    AlignmentView alview, String wsurl2)
371    {
372  2 super();
373  2 this.alignFrame = alframe;
374  2 currentView = alframe.getCurrentView().getAlignment();
375  2 featureSettings = alframe.getFeatureRenderer().getSettings();
376  2 defGapChar = alframe.getViewport().getGapCharacter();
377  2 this.wsInfo = wsinfo2;
378  2 this.input = alview;
379  2 WsUrl = wsurl2;
380  2 if (alframe != null)
381    {
382  2 List<AlignedCodonFrame> cf = alframe.getViewport().getAlignment()
383    .getCodonFrames();
384  2 if (cf != null)
385    {
386  2 codonframe = new ArrayList<AlignedCodonFrame>();
387  2 codonframe.addAll(cf);
388    }
389    }
390    }
391   
 
392  0 toggle protected AlignFrame getRequestingAlignFrame()
393    {
394  0 return this.alignFrame;
395    }
396    }