Clover icon

Coverage Report

  1. Project Clover database Mon Nov 11 2024 17:27:16 GMT
  2. Package jalview.ws

File AWSThread.java

 

Coverage histogram

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

Code metrics

38
88
15
1
394
243
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.Console;
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 Console.debug("Job " + j + " Result state " + jobs[j].getState()
131    + "(ServerError=" + jobs[j].isServerError() + ")");
132    } catch (Exception ex)
133    {
134    // Deal with Transaction exceptions
135  0 wsInfo.appendProgressText(jobs[j].jobnum, MessageManager
136    .formatMessage("info.server_exception", new Object[]
137    { WebServiceName, ex.getMessage() }));
138    // always output the exception's stack trace to the log
139  0 Console.warn(WebServiceName + " job(" + jobs[j].jobnum
140    + ") Server exception.");
141    // todo: could limit trace to cause if this is a SOAPFaultException.
142  0 ex.printStackTrace();
143   
144  0 if (jobs[j].allowedServerExceptions > 0)
145    {
146  0 jobs[j].allowedServerExceptions--;
147  0 Console.debug("Sleeping after a server exception.");
148  0 try
149    {
150  0 Thread.sleep(5000);
151    } catch (InterruptedException ex1)
152    {
153    }
154    }
155    else
156    {
157  0 Console.warn("Dropping job " + j + " " + jobs[j].jobId);
158  0 jobs[j].subjobComplete = true;
159  0 wsInfo.setStatus(jobs[j].jobnum,
160    WebserviceInfo.STATE_STOPPED_SERVERERROR);
161    }
162    } catch (OutOfMemoryError er)
163    {
164  0 jobComplete = true;
165  0 jobs[j].subjobComplete = true;
166  0 jobs[j].clearResponse(); // may contain out of date result data
167  0 wsInfo.setStatus(jobs[j].jobnum,
168    WebserviceInfo.STATE_STOPPED_ERROR);
169  0 Console.error("Out of memory when retrieving Job " + j + " id:"
170    + WsUrl + "/" + jobs[j].jobId, er);
171  0 new jalview.gui.OOMWarning(
172    "retrieving result for " + WebServiceName, er);
173  0 System.gc();
174    }
175    }
176  1 jstate.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
177    }
178    // Decide on overall state based on collected jobs[] states
179  0 updateGlobalStatus(jstate);
180  0 if (!jobComplete)
181    {
182  0 try
183    {
184  0 Thread.sleep(5000);
185    } catch (InterruptedException e)
186    {
187  0 Console.debug("Interrupted sleep waiting for next job poll.", e);
188    }
189    // jalview.bin.Console.outPrintln("I'm alive "+alTitle);
190    }
191    }
192  0 if (jobComplete && jobs != null)
193    {
194  0 parseResult(); // tidy up and make results available to user
195    }
196    else
197    {
198  0 Console.debug(
199    "WebServiceJob poll loop finished with no jobs created.");
200  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
201  0 wsInfo.appendProgressText(
202    MessageManager.getString("info.no_jobs_ran"));
203  0 wsInfo.setFinishedNoResults();
204    }
205    }
206   
 
207  0 toggle protected void updateGlobalStatus(JobStateSummary jstate)
208    {
209  0 if (jstate.running > 0)
210    {
211  0 wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
212    }
213  0 else if (jstate.queuing > 0)
214    {
215  0 wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
216    }
217    else
218    {
219  0 jobComplete = true;
220  0 if (jstate.finished > 0)
221    {
222  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
223    }
224  0 else if (jstate.error > 0)
225    {
226  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
227    }
228  0 else if (jstate.serror > 0)
229    {
230  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
231    }
232    }
233    }
234   
 
235  0 toggle public AWSThread()
236    {
237  0 super();
238    }
239   
 
240  0 toggle public AWSThread(Runnable target)
241    {
242  0 super(target);
243    }
244   
 
245  0 toggle public AWSThread(String name)
246    {
247  0 super(name);
248    }
249   
 
250  0 toggle public AWSThread(ThreadGroup group, Runnable target)
251    {
252  0 super(group, target);
253    }
254   
 
255  0 toggle public AWSThread(ThreadGroup group, String name)
256    {
257  0 super(group, name);
258    }
259   
 
260  0 toggle public AWSThread(Runnable target, String name)
261    {
262  0 super(target, name);
263    }
264   
 
265  0 toggle public AWSThread(ThreadGroup group, Runnable target, String name)
266    {
267  0 super(group, target, name);
268    }
269   
270    /**
271    * query web service for status of job. on return, job.result must not be null
272    * - if it is then it will be assumed that the job status query timed out and
273    * a server exception will be logged.
274    *
275    * @param job
276    * @throws Exception
277    * will be logged as a server exception for this job
278    */
279    public abstract void pollJob(AWsJob job) throws Exception;
280   
281    /**
282    * submit job to web service
283    *
284    * @param job
285    */
286    public abstract void StartJob(AWsJob job);
287   
288    /**
289    * process the set of AWsJob objects into a set of results, and tidy up.
290    */
291    public abstract void parseResult();
292   
293    /**
294    * helper function to conserve dataset references to sequence objects returned
295    * from web services 1. Propagates AlCodonFrame data from
296    * <code>codonframe</code> to <code>al</code> TODO: refactor to datamodel
297    *
298    * @param al
299    */
 
300  0 toggle public void propagateDatasetMappings(Alignment al)
301    {
302  0 if (codonframe != null)
303    {
304  0 SequenceI[] alignment = al.getSequencesArray();
305  0 for (int sq = 0; sq < alignment.length; sq++)
306    {
307  0 for (AlignedCodonFrame acf : codonframe)
308    {
309  0 final SequenceI seq = alignment[sq];
310  0 if (acf != null && acf.involvesSequence(seq))
311    {
312  0 al.addCodonFrame(acf);
313  0 break;
314    }
315    }
316    }
317    }
318    }
319   
 
320  0 toggle public AWSThread(ThreadGroup group, Runnable target, String name,
321    long stackSize)
322    {
323  0 super(group, target, name, stackSize);
324    }
325   
326    /**
327    *
328    * @return gap character to use for any alignment generation
329    */
 
330  0 toggle public char getGapChar()
331    {
332  0 return defGapChar;
333    }
334   
335    /**
336    *
337    * @param alignFrame
338    * reference for copying mappings across
339    * @param wsInfo
340    * gui attachment point
341    * @param input
342    * input data for the calculation
343    * @param webServiceName
344    * name of service
345    * @param wsUrl
346    * url of the service being invoked
347    */
 
348  0 toggle public AWSThread(AlignFrame alignFrame, WebserviceInfo wsinfo,
349    AlignmentView input, String webServiceName, String wsUrl)
350    {
351  0 this(alignFrame, wsinfo, input, wsUrl);
352  0 WebServiceName = webServiceName;
353    }
354   
355    /**
356    * Extracts additional info from alignment view's context.
357    *
358    * @param alframe
359    * - reference for copying mappings and display styles across
360    * @param wsinfo2
361    * - gui attachment point - may be null
362    * @param alview
363    * - input data for the calculation
364    * @param wsurl2
365    * - url of the service being invoked
366    */
 
367  2 toggle public AWSThread(AlignFrame alframe, WebserviceInfo wsinfo2,
368    AlignmentView alview, String wsurl2)
369    {
370  2 super();
371  2 this.alignFrame = alframe;
372  2 currentView = alframe.getCurrentView().getAlignment();
373  2 featureSettings = alframe.getFeatureRenderer().getSettings();
374  2 defGapChar = alframe.getViewport().getGapCharacter();
375  2 this.wsInfo = wsinfo2;
376  2 this.input = alview;
377  2 WsUrl = wsurl2;
378  2 if (alframe != null)
379    {
380  2 List<AlignedCodonFrame> cf = alframe.getViewport().getAlignment()
381    .getCodonFrames();
382  2 if (cf != null)
383    {
384  2 codonframe = new ArrayList<AlignedCodonFrame>();
385  2 codonframe.addAll(cf);
386    }
387    }
388    }
389   
 
390  0 toggle protected AlignFrame getRequestingAlignFrame()
391    {
392  0 return this.alignFrame;
393    }
394    }