Still not working code
[jabaws.git] / webservices / compbio / stat / collector / ExecutionStatUpdater.java
1 /* Copyright (c) 2013 Alexander Sherstnev\r
2  * Copyright (c) 2011 Peter Troshin\r
3  *  \r
4  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0     \r
5  * \r
6  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
7  *  Apache License version 2 as published by the Apache Software Foundation\r
8  * \r
9  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
10  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
11  *  License for more details.\r
12  * \r
13  *  A copy of the license is in apache_license.txt. It is also available here:\r
14  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
15  * \r
16  * Any republication or derived work distributed in source code form\r
17  * must include this copyright and license notice.\r
18  */\r
19 package compbio.stat.collector;\r
20 \r
21 import java.io.File;\r
22 import java.io.FileFilter;\r
23 import java.io.IOException;\r
24 import java.sql.SQLException;\r
25 import java.text.SimpleDateFormat;\r
26 import java.util.ArrayList;\r
27 import java.util.Date;\r
28 import java.util.HashSet;\r
29 import java.util.List;\r
30 import java.util.Set;\r
31 \r
32 import com.beust.jcommander.JCommander;\r
33 import com.beust.jcommander.Parameter;\r
34 \r
35 import org.apache.log4j.Logger;\r
36 \r
37 import compbio.engine.client.PathValidator;\r
38 import compbio.engine.client.SkeletalExecutable;\r
39 \r
40 /**\r
41  * Class assumptions: 1. Number of runs of each WS = number of folders with name\r
42  * 2. Number of successful runs = all runs with no result file 3. Per period of\r
43  * time = limit per file creating time 4. Runtime (avg/max) = finish time -\r
44  * start time 5. Task & result size = result.size\r
45  * \r
46  * Abandoned runs - not collected runs\r
47  * \r
48  * Cancelled runs - cancelled\r
49  * \r
50  * Cluster vs local runs\r
51  * \r
52  * Reasons for failure = look in the err out?\r
53  * \r
54  * \r
55  * Metadata required:\r
56  * \r
57  * work directory for local and cluster tasks = from Helper or cmd parameter. WS\r
58  * names - enumeration. Status file names and content.\r
59  * \r
60  * @author Peter Troshin\r
61  * @author Alexander Sherstnev\r
62  * \r
63  */\r
64 \r
65 class mainJCommander {\r
66         @Parameter\r
67         private List<String> parameters = new ArrayList<String>();\r
68 \r
69         @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")\r
70         Integer verbose = 1;\r
71 \r
72         @Parameter(names = "-start", description = "Start time")\r
73         String starttime;\r
74 \r
75         @Parameter(names = "-end", description = "Start time")\r
76         String endtime;\r
77 \r
78         @Parameter(names = "-db", description = "Path to database")\r
79         String dbname;\r
80 }\r
81 \r
82 public class ExecutionStatUpdater {\r
83         static SimpleDateFormat DF = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");\r
84         private static final Logger log = Logger.getLogger(ExecutionStatUpdater.class);\r
85 \r
86         final private File workingDirectory;\r
87         final private List<JobStat> stats;\r
88         /**\r
89          * Consider the job that has been working for longer than timeOutInHours\r
90          * completed, whatever the outcome\r
91          */\r
92         final private int timeOutInHours;\r
93 \r
94         /**\r
95          * List subdirectories in the job directory\r
96          * \r
97          * @param workingDirectory\r
98          * @param timeOutInHours\r
99          */\r
100         public ExecutionStatUpdater(String workingDirectory, int timeOutInHours) {\r
101                 log.info("Starting stat collector for directory: " + workingDirectory);\r
102                 log.info("Maximum allowed runtime(h): " + timeOutInHours);\r
103                 if (!PathValidator.isValidDirectory(workingDirectory)) {\r
104                         throw new IllegalArgumentException("workingDirectory '" + workingDirectory + "' does not exist!");\r
105                 }\r
106                 this.workingDirectory = new File(workingDirectory);\r
107                 stats = new ArrayList<JobStat>();\r
108                 if (timeOutInHours <= 0) {\r
109                         throw new IllegalArgumentException("Timeout value must be greater than 0! Given value: " + timeOutInHours);\r
110                 }\r
111                 this.timeOutInHours = timeOutInHours;\r
112         }\r
113 \r
114         boolean hasCompleted(JobDirectory jd) {\r
115                 JobStat jstat = jd.getJobStat();\r
116                 if (jstat.hasResult() || jstat.getIsCancelled() || jstat.getIsFinished() || hasTimedOut(jd)) {\r
117                         return true;\r
118                 }\r
119                 return false;\r
120         }\r
121 \r
122         boolean hasTimedOut(JobDirectory jd) {\r
123                 return ((System.currentTimeMillis() - jd.jobdir.lastModified()) / (1000 * 60 * 60)) > timeOutInHours;\r
124         }\r
125 \r
126         /*\r
127          * Make sure that collectStatistics methods was called prior to calling\r
128          * this! TODO consider running collectStatistics from here on the first call\r
129          */\r
130         StatProcessor getStats() {\r
131                 if (stats.isEmpty()) {\r
132                         log.info("Please make sure collectStatistics method was called prior to calling getStats()!");\r
133                 }\r
134                 return new StatProcessor(stats);\r
135         }\r
136 \r
137         void writeStatToDB() throws SQLException {\r
138                 Set<JobStat> rjobs = new HashSet<JobStat>(stats);\r
139                 StatDB statdb = new StatDB();\r
140                 log.debug("Removing records that has already been recorded");\r
141                 statdb.removeRecordedJobs(rjobs);\r
142                 log.debug("New records left: " + rjobs.size());\r
143                 statdb.insertData(rjobs);\r
144         }\r
145 \r
146         /**\r
147          * main function\r
148          */\r
149         public static void main(String[] args) throws IOException, SQLException {\r
150                 mainJCommander jct = new mainJCommander();\r
151                 new JCommander(jct, args);\r
152                 String WorkingDir = "jobout";\r
153                 String StartTime = jct.starttime;\r
154                 String EndTime = jct.endtime;\r
155                 String dbname = jct.dbname;\r
156                 long StartTimeLong = 0;\r
157                 long EndTimeLong = 0;\r
158 \r
159                 ExecutionStatUpdater esu = new ExecutionStatUpdater(WorkingDir, 1);\r
160                 esu.collectStatistics(StartTimeLong, EndTimeLong);\r
161                 esu.writeStatToDB();\r
162         }\r
163 \r
164         static FileFilter directories = new FileFilter() {\r
165                 @Override\r
166                 public boolean accept(File pathname) {\r
167                         return pathname.isDirectory() && !pathname.getName().startsWith(".");\r
168                 }\r
169         };\r
170 \r
171         // TODO test!\r
172         private void collectStatistics(long StartTime, long EndTime) {\r
173                 // clear stats array;\r
174                 stats.clear();\r
175                 File[] dirs = workingDirectory.listFiles(directories);\r
176                 for (File dir : dirs) {\r
177                         // skip work directory with test inputs and out of ordered time\r
178                         // range\r
179                         log.debug("check directory: " + dir.getName() + "...");\r
180                         if (InputFilter.accept(new File(dir.getPath() + File.separator + SkeletalExecutable.INPUT)) && StartTime < dir.lastModified()\r
181                                         && dir.lastModified() < EndTime) {\r
182                                 JobDirectory jd = new JobDirectory(dir);\r
183                                 JobStat jstat = jd.getJobStat();\r
184                                 // Do not record stats on the job that has not completed yet\r
185                                 if (hasCompleted(jd)) {\r
186                                         stats.add(jstat);\r
187                                 } else {\r
188                                         log.debug("Skipping the job: " + jstat + " as it has not completed yet");\r
189                                 }\r
190                         } else {\r
191                                 log.trace("training input: " + dir.getName() + File.separator + SkeletalExecutable.INPUT);\r
192                         }\r
193                 }\r
194         }\r
195 \r
196 }\r