Further work on statistics display
[jabaws.git] / webservices / compbio / stat / collector / StatDB.java
1 package compbio.stat.collector;\r
2 \r
3 import java.sql.Connection;\r
4 import java.sql.DriverManager;\r
5 import java.sql.PreparedStatement;\r
6 import java.sql.ResultSet;\r
7 import java.sql.SQLException;\r
8 import java.sql.Statement;\r
9 import java.sql.Timestamp;\r
10 import java.util.ArrayList;\r
11 import java.util.Date;\r
12 import java.util.List;\r
13 import java.util.Set;\r
14 \r
15 import org.apache.log4j.Logger;\r
16 \r
17 import compbio.engine.conf.PropertyHelperManager;\r
18 import compbio.util.Util;\r
19 import compbio.ws.client.Services;\r
20 \r
21 /**\r
22  * The database must be stored in the application root directory and called\r
23  * "ExecutionStatistic"\r
24  * \r
25  * @author pvtroshin\r
26  * \r
27  */\r
28 public class StatDB {\r
29 \r
30         private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver";\r
31         private static final String protocol = "jdbc:derby:";\r
32         private static final String statDBName = "ExecutionStatistic";\r
33 \r
34         private static final Logger log = Logger.getLogger(StatDB.class);\r
35 \r
36         static Connection conn;\r
37 \r
38         private synchronized static Connection getDBConnection()\r
39                         throws SQLException {\r
40 \r
41                 if (conn != null && !conn.isClosed()) {\r
42                         return conn;\r
43                 } else {\r
44                         String dbpath = PropertyHelperManager.getLocalPath();\r
45                         log.info("Looking for JABAWS access statistics database at: "\r
46                                         + dbpath);\r
47                         System.setProperty("derby.system.home", dbpath);\r
48                         conn = DriverManager.getConnection(protocol + statDBName\r
49                                         + ";create=false");\r
50 \r
51                         conn.setAutoCommit(true);\r
52                 }\r
53                 return conn;\r
54         }\r
55 \r
56         public StatDB() throws SQLException {\r
57                 this.conn = getDBConnection();\r
58         }\r
59 \r
60         /**\r
61          * Connect to test database\r
62          * \r
63          * @param ignored\r
64          * @throws SQLException\r
65          */\r
66         StatDB(boolean ignored) throws SQLException {\r
67                 this.conn = getTestDBConnection();\r
68         }\r
69 \r
70         private static Connection getTestDBConnection() throws SQLException {\r
71                 System.setProperty("derby.system.home", "testsrc/testdata");\r
72                 Connection conn = DriverManager.getConnection(protocol + statDBName\r
73                                 + ";create=false");\r
74                 conn.setAutoCommit(true);\r
75                 return conn;\r
76         }\r
77 \r
78         // ServiceName,jobname,start,finish,inputSize,resultSize,isCancelled,isCollected\r
79         /**\r
80          * \r
81          * rs.getBoolean(i) will return true for any non-zero value and false for 0\r
82          * on SMALLINT data column.\r
83          * \r
84          * @throws SQLException\r
85          */\r
86         private void createStatTable() throws SQLException {\r
87 \r
88                 /*\r
89                  * Creating a statement object that we can use for running various SQL\r
90                  * statements commands against the database.\r
91                  */\r
92                 Statement s = conn.createStatement();\r
93                 String create = "create table exec_stat("\r
94                                 + "number INT GENERATED ALWAYS AS IDENTITY,"\r
95                                 + "service_name VARCHAR(15) NOT NULL, "\r
96                                 + "cluster_job_id VARCHAR(30), "\r
97                                 + "job_id VARCHAR(35) NOT NULL PRIMARY KEY, "\r
98                                 + "start TIMESTAMP," + "finish TIMESTAMP,"\r
99                                 + "inputsize BIGINT," + "resultsize BIGINT,"\r
100                                 + "isCancelled SMALLINT NOT NULL,"\r
101                                 + "isCollected SMALLINT NOT NULL, "\r
102                                 + "isClusterJob SMALLINT NOT NULL)";\r
103                 // We create a table...\r
104                 System.out.println(create);\r
105                 s.execute(create);\r
106                 s.close();\r
107                 conn.close();\r
108         }\r
109 \r
110         void insertData(Set<JobStat> jobstatus) throws SQLException {\r
111                 System.out.println("Inserting " + jobstatus.size());\r
112 \r
113                 conn.setAutoCommit(false);\r
114                 String insert = "insert into exec_stat (service_name, cluster_job_id, job_id, start, finish, "\r
115                                 + "inputsize, resultsize, isCancelled, isCollected, isClusterJob) "\r
116                                 + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";\r
117                 PreparedStatement pstm = conn.prepareStatement(insert);\r
118                 for (JobStat js : jobstatus) {\r
119                         // Has to present\r
120                         pstm.setString(1, js.webService.toString());\r
121 \r
122                         if (!Util.isEmpty(js.clusterJobId)) {\r
123                                 pstm.setString(2, js.clusterJobId);\r
124                         } else {\r
125                                 pstm.setString(2, null);\r
126                         }\r
127                         // Has to present\r
128                         pstm.setString(3, js.jobname);\r
129 \r
130                         if (js.start != ExecutionStatCollector.UNDEFINED) {\r
131                                 pstm.setTimestamp(4, new Timestamp(js.start));\r
132                         } else {\r
133                                 pstm.setTimestamp(4, null);\r
134                         }\r
135                         if (js.finish != ExecutionStatCollector.UNDEFINED) {\r
136                                 pstm.setTimestamp(5, new Timestamp(js.finish));\r
137                         } else {\r
138                                 pstm.setTimestamp(5, null);\r
139                         }\r
140                         // -1 if UNDEFINED\r
141                         pstm.setLong(6, js.inputSize);\r
142                         // -1 if UNDEFINED\r
143                         pstm.setLong(7, js.resultSize);\r
144 \r
145                         pstm.setBoolean(8, js.isCancelled);\r
146                         pstm.setBoolean(9, js.isCollected);\r
147                         pstm.setBoolean(10, js.isClusterJob());\r
148                         pstm.executeUpdate();\r
149                 }\r
150                 conn.commit();\r
151                 pstm.close();\r
152         }\r
153 \r
154         public Date getEarliestRecord() throws SQLException {\r
155                 String query = "select min(start) from exec_stat";\r
156                 Statement st = conn.createStatement();\r
157                 ResultSet res = st.executeQuery(query);\r
158                 boolean exist = res.next();\r
159                 Date date = new Date();\r
160                 if (exist) {\r
161                         date = res.getDate(1);\r
162                 }\r
163 \r
164                 res.close();\r
165                 st.close();\r
166                 return date;\r
167         }\r
168 \r
169         public List<JobStat> readData(Timestamp from, Timestamp to,\r
170                         Services wservice, Boolean clusterOnly) throws SQLException {\r
171 \r
172                 String query = "select service_name, cluster_job_id, job_id, start, finish, inputsize, "\r
173                                 + "resultsize, isCancelled, isCollected from exec_stat where start BETWEEN ? and ? ";\r
174 \r
175                 if (wservice != null) {\r
176                         query += " and service_name=? ";\r
177                 }\r
178 \r
179                 if (clusterOnly != null) {\r
180                         if (clusterOnly) {\r
181                                 query += " and isClusterJob!=0 ";\r
182                         } else {\r
183                                 query += " and isClusterJob=0 ";\r
184                         }\r
185                 }\r
186 \r
187                 PreparedStatement pstm = conn.prepareStatement(query);\r
188                 pstm.setTimestamp(1, from);\r
189                 pstm.setTimestamp(2, to);\r
190                 if (wservice != null) {\r
191                         pstm.setString(3, wservice.toString());\r
192                 }\r
193                 pstm.execute();\r
194                 List<JobStat> stats = new ArrayList<JobStat>();\r
195                 ResultSet rs = pstm.getResultSet();\r
196                 while (rs.next()) {\r
197                         stats.add(JobStat.newInstance(Services.getService(rs.getString(1)),\r
198                                         rs.getString(2), rs.getString(3), rs.getTimestamp(4),\r
199                                         rs.getTimestamp(5), rs.getLong(6), rs.getLong(7),\r
200                                         rs.getBoolean(8), rs.getBoolean(9)));\r
201                 }\r
202                 rs.close();\r
203                 pstm.close();\r
204 \r
205                 return stats;\r
206         }\r
207         public void removeRecordedJobs(Set<JobStat> fsJobs) throws SQLException {\r
208 \r
209                 String query = "select job_id from exec_stat";\r
210 \r
211                 Statement st = conn.createStatement();\r
212                 ResultSet result = st.executeQuery(query);\r
213 \r
214                 while (result.next()) {\r
215                         String recordedJob = result.getString(1);\r
216                         JobStat recStat = JobStat.newIncompleteStat(recordedJob);\r
217                         if (fsJobs.contains(recStat)) {\r
218                                 fsJobs.remove(recStat);\r
219                         }\r
220                 }\r
221                 result.close();\r
222         }\r
223 \r
224         public void shutdownDBServer() {\r
225                 // ## DATABASE SHUTDOWN SECTION ##\r
226                 /***\r
227                  * In embedded mode, an application should shut down Derby. Shutdown\r
228                  * throws the XJ015 exception to confirm success.\r
229                  ***/\r
230                 try {\r
231                         if (conn != null) {\r
232                                 conn.close();\r
233                         }\r
234                 } catch (SQLException e) {\r
235                         System.err.println("Database commit failed with "\r
236                                         + e.getLocalizedMessage());\r
237                 }\r
238                 boolean gotSQLExc = false;\r
239                 try {\r
240                         DriverManager.getConnection("jdbc:derby:;shutdown=true");\r
241                 } catch (SQLException se) {\r
242                         if (se.getSQLState().equals("XJ015")) {\r
243                                 gotSQLExc = true;\r
244                         }\r
245                 }\r
246                 if (!gotSQLExc) {\r
247                         System.err.println("Database did not shut down normally");\r
248                 } else {\r
249                         System.out.println("Database shut down normally");\r
250                 }\r
251         }\r
252         public static void main(String[] args) throws SQLException {\r
253                 // new StatDB().createStatTable();\r
254                 // insertData(null);\r
255                 /*\r
256                  * StatDB statdb = new StatDB(); Date from = new Date();\r
257                  * from.setMonth(1); System.out.println(new\r
258                  * StatProcessor(statdb.readData( new Timestamp(from.getTime()), new\r
259                  * Timestamp(new Date().getTime()), null, null)).reportStat());\r
260                  */\r
261         }\r
262 }\r