JWS-96 initial code for the stat crawler
authorSasha Sherstnev <a.sherstnev@dundee.ac.uk>
Mon, 16 Jun 2014 06:50:05 +0000 (07:50 +0100)
committerSasha Sherstnev <a.sherstnev@dundee.ac.uk>
Mon, 16 Jun 2014 06:50:05 +0000 (07:50 +0100)
.classpath
lib/jcommander-1.30.jar [new file with mode: 0644]
webservices/compbio/stat/collector/ExecutionStatUpdater.java [new file with mode: 0644]
webservices/compbio/stat/collector/StatDB.java
webservices/compbio/stat/servlet/StatisticCollector.java
webservices/compbio/ws/server/MainManager.java

index 46b788d..794a7ca 100644 (file)
@@ -17,5 +17,6 @@
        <classpathentry kind="lib" path="WEB-INF/lib/standard-1.1.2.jar"/>
        <classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v7.0"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.7.0_45"/>
+       <classpathentry kind="lib" path="lib/jcommander-1.30.jar"/>
        <classpathentry kind="output" path="WEB-INF/classes"/>
 </classpath>
diff --git a/lib/jcommander-1.30.jar b/lib/jcommander-1.30.jar
new file mode 100644 (file)
index 0000000..ec6c420
Binary files /dev/null and b/lib/jcommander-1.30.jar differ
diff --git a/webservices/compbio/stat/collector/ExecutionStatUpdater.java b/webservices/compbio/stat/collector/ExecutionStatUpdater.java
new file mode 100644 (file)
index 0000000..8e9a6e4
--- /dev/null
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013 Alexander Sherstnev\r
+ * Copyright (c) 2011 Peter Troshin\r
+ *  \r
+ *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0     \r
+ * \r
+ *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
+ *  Apache License version 2 as published by the Apache Software Foundation\r
+ * \r
+ *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
+ *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
+ *  License for more details.\r
+ * \r
+ *  A copy of the license is in apache_license.txt. It is also available here:\r
+ * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
+ * \r
+ * Any republication or derived work distributed in source code form\r
+ * must include this copyright and license notice.\r
+ */\r
+package compbio.stat.collector;\r
+\r
+import java.io.File;\r
+import java.io.FileFilter;\r
+import java.io.IOException;\r
+import java.sql.SQLException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import com.beust.jcommander.JCommander;\r
+import com.beust.jcommander.Parameter;\r
+\r
+import org.apache.log4j.Logger;\r
+\r
+import compbio.engine.client.PathValidator;\r
+import compbio.engine.client.SkeletalExecutable;\r
+import compbio.util.FileUtil;\r
+\r
+/**\r
+ * Class assumptions: 1. Number of runs of each WS = number of folders with name\r
+ * 2. Number of successful runs = all runs with no result file 3. Per period of\r
+ * time = limit per file creating time 4. Runtime (avg/max) = finish time -\r
+ * start time 5. Task & result size = result.size\r
+ * \r
+ * Abandoned runs - not collected runs\r
+ * \r
+ * Cancelled runs - cancelled\r
+ * \r
+ * Cluster vs local runs\r
+ * \r
+ * Reasons for failure = look in the err out?\r
+ * \r
+ * \r
+ * Metadata required:\r
+ * \r
+ * work directory for local and cluster tasks = from Helper or cmd parameter. WS\r
+ * names - enumeration. Status file names and content.\r
+ * \r
+ * @author Peter Troshin\r
+ * @author Alexander Sherstnev\r
+ * \r
+ */\r
+\r
+class mainJCommander {\r
+       @Parameter\r
+       private List<String> parameters = new ArrayList<String>();\r
+\r
+       @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")\r
+       Integer verbose = 1;\r
+\r
+       @Parameter(names = "-start", description = "Start time")\r
+       String starttime;\r
+\r
+       @Parameter(names = "-end", description = "Start time")\r
+       String endtime;\r
+\r
+       @Parameter(names = "-db", description = "Path to database")\r
+       String dbname;\r
+}\r
+\r
+public class ExecutionStatUpdater {\r
+       static SimpleDateFormat DF = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");\r
+       private static final Logger log = Logger.getLogger(ExecutionStatUpdater.class);\r
+\r
+       final private File workingDirectory;\r
+       final private List<JobStat> stats;\r
+       /**\r
+        * Consider the job that has been working for longer than timeOutInHours\r
+        * completed, whatever the outcome\r
+        */\r
+       final private int timeOutInHours;\r
+\r
+       /**\r
+        * List subdirectories in the job directory\r
+        * \r
+        * @param workingDirectory\r
+        * @param timeOutInHours\r
+        */\r
+       public ExecutionStatUpdater(String workingDirectory, int timeOutInHours) {\r
+               log.info("Starting stat collector for directory: " + workingDirectory);\r
+               log.info("Maximum allowed runtime(h): " + timeOutInHours);\r
+               if (!PathValidator.isValidDirectory(workingDirectory)) {\r
+                       throw new IllegalArgumentException("workingDirectory '" + workingDirectory + "' does not exist!");\r
+               }\r
+               this.workingDirectory = new File(workingDirectory);\r
+               stats = new ArrayList<JobStat>();\r
+               if (timeOutInHours <= 0) {\r
+                       throw new IllegalArgumentException("Timeout value must be greater than 0! Given value: " + timeOutInHours);\r
+               }\r
+               this.timeOutInHours = timeOutInHours;\r
+       }\r
+\r
+       boolean hasCompleted(JobDirectory jd) {\r
+               JobStat jstat = jd.getJobStat();\r
+               if (jstat.hasResult() || jstat.getIsCancelled() || jstat.getIsFinished() || hasTimedOut(jd)) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       boolean hasTimedOut(JobDirectory jd) {\r
+               return ((System.currentTimeMillis() - jd.jobdir.lastModified()) / (1000 * 60 * 60)) > timeOutInHours;\r
+       }\r
+\r
+       /*\r
+        * Make sure that collectStatistics methods was called prior to calling\r
+        * this! TODO consider running collectStatistics from here on the first call\r
+        */\r
+       StatProcessor getStats() {\r
+               if (stats.isEmpty()) {\r
+                       log.info("Please make sure collectStatistics method was called prior to calling getStats()!");\r
+               }\r
+               return new StatProcessor(stats);\r
+       }\r
+\r
+       void writeStatToDB() throws SQLException {\r
+               Set<JobStat> rjobs = new HashSet<JobStat>(stats);\r
+               StatDB statdb = new StatDB();\r
+               log.debug("Removing records that has already been recorded");\r
+               statdb.removeRecordedJobs(rjobs);\r
+               log.debug("New records left: " + rjobs.size());\r
+               statdb.insertData(rjobs);\r
+       }\r
+\r
+       /**\r
+        * main function\r
+        */\r
+       public static void main(String[] args) throws IOException, SQLException {\r
+               mainJCommander jct = new mainJCommander();\r
+               new JCommander(jct, args);\r
+               String WorkingDir = "jobout";\r
+               String StartTime = jct.starttime;\r
+               String EndTime = jct.endtime;\r
+               String dbname = jct.dbname;\r
+               long StartTimeLong = 0;\r
+               long EndTimeLong = 0;\r
+\r
+               ExecutionStatUpdater esu = new ExecutionStatUpdater(WorkingDir, 1);\r
+               esu.collectStatistics(StartTimeLong, EndTimeLong);\r
+               esu.writeStatToDB();\r
+       }\r
+\r
+       static FileFilter directories = new FileFilter() {\r
+               @Override\r
+               public boolean accept(File pathname) {\r
+                       return pathname.isDirectory() && !pathname.getName().startsWith(".");\r
+               }\r
+       };\r
+\r
+       // TODO test!\r
+       private void collectStatistics(long StartTime, long EndTime) {\r
+               // clear stats array;\r
+               stats.clear();\r
+               File[] dirs = workingDirectory.listFiles(directories);\r
+               for (File dir : dirs) {\r
+                       // skip work directory with test inputs and out of ordered time\r
+                       // range\r
+                       log.debug("check directory: " + dir.getName() + "...");\r
+                       if (InputFilter.accept(new File(dir.getPath() + File.separator + SkeletalExecutable.INPUT)) && StartTime < dir.lastModified()\r
+                                       && dir.lastModified() < EndTime) {\r
+                               JobDirectory jd = new JobDirectory(dir);\r
+                               JobStat jstat = jd.getJobStat();\r
+                               // Do not record stats on the job that has not completed yet\r
+                               if (hasCompleted(jd)) {\r
+                                       stats.add(jstat);\r
+                               } else {\r
+                                       log.debug("Skipping the job: " + jstat + " as it has not completed yet");\r
+                               }\r
+                       } else {\r
+                               log.trace("training input: " + dir.getName() + File.separator + SkeletalExecutable.INPUT);\r
+                       }\r
+               }\r
+       }\r
+\r
+}\r
index 32b7fde..45947a2 100644 (file)
@@ -53,6 +53,10 @@ public class StatDB {
        static Connection conn;\r
 \r
        private synchronized static Connection getDBConnection() throws SQLException {\r
+               return getDBConnection(statDBName);\r
+       }\r
+\r
+       private synchronized static Connection getDBConnection(String dbname) throws SQLException {\r
 \r
                if (conn != null && !conn.isClosed()) {\r
                        return conn;\r
@@ -64,7 +68,7 @@ public class StatDB {
                                // Apparently under Tomcat webapp you cannot rely on Java\r
                                // auto discovery and have to register the driver explicitly\r
                                Class.forName(driver);\r
-                               conn = DriverManager.getConnection(protocol + statDBName + ";create=false");\r
+                               conn = DriverManager.getConnection(protocol + dbname + ";create=false");\r
 \r
                                conn.setAutoCommit(true);\r
                        } catch (ClassNotFoundException e) {\r
@@ -74,6 +78,11 @@ public class StatDB {
                return conn;\r
        }\r
 \r
+       \r
+       public StatDB(String dbname) throws SQLException {\r
+               this.conn = getDBConnection(dbname);\r
+       }\r
+\r
        public StatDB() throws SQLException {\r
                this.conn = getDBConnection();\r
        }\r
index e305fa5..5d7c251 100644 (file)
@@ -108,6 +108,10 @@ public class StatisticCollector implements ServletContextListener {
                return getStringProperty(ph.getProperty("cluster.tmp.directory"));\r
        }\r
 \r
+       static String getStatDBname() {\r
+               return getStringProperty(ph.getProperty("cluster.tmp.directory"));\r
+       }\r
+\r
        static int getClusterJobTimeOut() {\r
                int maxRunTime = 24 * 7;\r
                String clusterMaxRuntime = ph.getProperty("cluster.stat.maxruntime");\r
index 63267c7..8d57254 100644 (file)
@@ -28,7 +28,6 @@ import javax.servlet.ServletContextListener;
 import org.apache.log4j.Logger;\r
 \r
 import compbio.stat.collector.DirCleaner;\r
-import compbio.stat.collector.StatDB;\r
 import compbio.engine.conf.PropertyHelperManager;\r
 import compbio.engine.local.ExecutableWrapper;\r
 import compbio.engine.local.LocalExecutorService;\r
@@ -75,7 +74,6 @@ public class MainManager implements ServletContextListener {
                        log.info("Local engine is shutdown OK");\r
                        ExecutableWrapper.shutdownService();\r
                        log.info("Individual executables stream engine is shutdown OK");\r
-                       StatDB.shutdownDBServer();\r
        }\r
 \r
        @Override\r