ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tools/ClusterConnection.java
Revision: 43
Committed: Wed Mar 22 09:30:40 2006 UTC (18 years, 6 months ago) by duarte
File size: 16274 byte(s)
Log Message:
Added executeSql method
Line User Rev File contents
1 duarte 16 package tools;
2 duarte 15 import java.sql.*;
3    
4     /**
5     * ClusterConnection class to wrap the master/node mysql servers so that is transparent to other programs
6     * @author Jose Duarte
7     */
8    
9     public class ClusterConnection {
10    
11 duarte 34 private final String URL= "jdbc:mysql://";
12     private String MASTERDB="key_master";
13     private final String MASTERHOST="white";
14 duarte 15 private Connection nCon;
15     private Connection mCon;
16     public String keyTable;
17     public String key;
18     public String idxColumn;
19     public String host;
20     public String db;
21     private String user;
22     private String password;
23 duarte 34
24     /**
25     * Create a ClusterConnection passing a key.
26 duarte 35 * @param db the database name
27     * @param key the key name: if asu_id is the ids from which my key is based on, then the key name is "asu"
28     * @param user the user name for connection to both master and nodes
29     * @param password the password for connection to both master and nodes
30 duarte 34 */
31 duarte 15 public ClusterConnection (String db,String key, String user,String password) {
32 duarte 17 new ClusterConnection(db,user,password);
33     this.key=key; //can't use the setKey method here before we've got the db field initialized
34 duarte 15 setIdxColumn();
35 duarte 34 setKeyTable(db);
36 duarte 15 }
37    
38 duarte 34 /**
39     * Create a ClusterConnection without passing a key. The key will be set later when we call createStatement(key,idx)
40 duarte 35 * @param db the database name
41     * @param user the user name for connection to both master and nodes
42     * @param password the password for connection to both master and nodes
43 duarte 34 */
44 duarte 15 public ClusterConnection (String db, String user,String password) {
45 duarte 17 loadMySQLDriver();
46 duarte 15 setDb(db);
47     setUser(user);
48     setPassword(password);
49     try {
50     // For nCon we create a connection to the master too.
51     // This is just a place holder because the actual node connection is not created until we create the statement
52     // If we don't do this then when closing the two connections an exception might occurr because we try to close a non existing object
53 duarte 34 this.nCon = DriverManager.getConnection(URL+MASTERHOST+"/"+MASTERDB,user,password);
54     this.mCon = DriverManager.getConnection(URL+MASTERHOST+"/"+MASTERDB,user,password);
55 duarte 15 }
56     catch(SQLException e){
57 duarte 33 System.err.println("SQLException: " + e.getMessage());
58     System.err.println("SQLState: " + e.getSQLState());
59     System.err.println("VendorError: " + e.getErrorCode());
60 duarte 34 System.err.println("Couldn't get connection to master host "+MASTERHOST+", db="+MASTERDB+", exiting.");
61 duarte 15 System.exit(2);
62     }
63     }
64    
65     public void loadMySQLDriver() {
66     try {
67     Class.forName("com.mysql.jdbc.Driver");
68     }
69     catch(Exception e) {
70 duarte 33 System.err.println(e.getMessage());
71     System.err.println("An exception occurred while loading the mysql jdbc driver, exiting.");
72 duarte 15 System.exit(1);
73     }
74     }
75     public void close() {
76     try {
77     this.nCon.close();
78     this.mCon.close();
79     }
80     catch(SQLException e) {
81 duarte 34 System.err.println("Couldn't close database connections for master: "+MASTERHOST+" and node: "+this.host+", exiting.");
82 duarte 33 System.err.println("SQLException: " + e.getMessage());
83     System.err.println("SQLState: " + e.getSQLState());
84 duarte 15 System.exit(3);
85     }
86     }
87    
88     public String getHost4Idx (int idx) {
89     String host="";
90     Statement S;
91     ResultSet R;
92     try {
93     S=mCon.createStatement();
94     String query="SELECT client_name FROM "+keyTable+" AS m INNER JOIN clients_names AS c "+
95     "ON (m.client_id=c.client_id) WHERE "+idxColumn+"="+idx+";";
96     R=S.executeQuery(query);
97     if (R.next()){
98     host=R.getString(1);
99     }
100     S.close();
101     R.close();
102     }
103     catch(SQLException e) {
104 duarte 33 System.err.println("Couldn't get the host name for idx "+idx+", exiting");
105     System.err.println("SQLException: " + e.getMessage());
106     System.err.println("SQLState: " + e.getSQLState());
107 duarte 15 System.exit(3);
108     }
109     return host;
110     }
111    
112     public void setHostFromIdx(int idx){
113     setHost(getHost4Idx(idx));
114     }
115    
116     public void setHost(String host) {
117     this.host=host;
118     try {
119 duarte 23 //Closing previous connection is essential
120     //If we don't close it a lot of connections stay open after using a ClusterConnection object for a while
121     this.nCon.close();
122 duarte 34 this.nCon=DriverManager.getConnection(URL+host+"/"+db,user,password);
123 duarte 15 }
124     catch (SQLException e){
125 duarte 33 System.err.println("SQLException: " + e.getMessage());
126     System.err.println("SQLState: " + e.getSQLState());
127 duarte 37 System.err.println("Couldn't get connection to node "+host+", database "+db+", exiting.");
128 duarte 15 System.exit(2);
129     }
130     }
131 duarte 35
132 duarte 34 /**
133     * This method is strictly private. We shouldn't call this from another class as a key might not be set when we call it
134     * and thus we can't get the client_id from the master key table. Only to be called from createStatement(key,idx)
135 duarte 35 * @param idx the value of the id for a certain key already set
136     * @return a Stament object with a connection to the node that contains idx for key
137 duarte 34 */
138     private Statement createStatement(int idx) { // to use when the field "key" is already set
139     setKeyTable();
140 duarte 15 setIdxColumn();
141     Statement S=null;
142     this.setHostFromIdx(idx);
143     try {
144     S=this.nCon.createStatement();
145     }
146     catch (SQLException e){
147 duarte 33 System.err.println("SQLException: " + e.getMessage());
148     System.err.println("SQLState: " + e.getSQLState());
149     System.err.println("Couldn't create statement for the node connection, idx= "+idx+", exiting.");
150 duarte 15 System.exit(2);
151     }
152     return S;
153     }
154 duarte 35
155 duarte 34 /**
156 duarte 35 * This method is used to create a statement passing the key and idx. It will create a connection the the right node
157     * and return a Statement for that connection
158     * @param idx the key name
159     * @param idx the id value for that key
160     * @return a Statement object with a connection to the node that contains idx for key
161 duarte 34 */
162 duarte 15 public Statement createStatement(String key,int idx) {
163     setKey(key);
164     return createStatement(idx);
165     }
166    
167 duarte 35 /**
168 duarte 43 * To execute a sql update/insert query in the right node given a query, key and idx. Just a shortcut not to have to do the create statement and execute
169     * @param query the SQL query
170     * @param key the name of the key
171     * @param idx the id value for that key
172     */
173     public void executeSql(String query,String key, int idx) {
174     Statement stmt;
175     try {
176     stmt = this.createStatement(key,idx);
177     stmt.execute(query);
178     stmt.close();
179     } catch (SQLException e) {
180     System.err.println("SQLException: " + e.getMessage());
181     System.err.println("SQLState: " + e.getSQLState());
182     System.err.println("VendorError: " + e.getErrorCode());
183     e.printStackTrace();
184     }
185     }
186    
187     /**
188 duarte 35 * To set keyTable field in constructor (i.e. first time)
189     * @param db the database name
190     */
191     public void setKeyTable(String db) {
192 duarte 15 this.keyTable=db+"_"+this.key+"_list_master";
193     }
194    
195 duarte 35 /**
196 duarte 43 * To set the keyTable field when db is already set
197 duarte 35 *
198     */
199     public void setKeyTable() {
200 duarte 15 this.keyTable=this.db+"_"+this.key+"_list_master";
201     }
202    
203 duarte 34 public String getKeyTable() {
204 duarte 15 return this.keyTable;
205     }
206    
207     public void setIdxColumn() {
208     this.idxColumn=this.key+"_id";
209     }
210    
211     public void setUser(String user) {
212     this.user=user;
213     }
214    
215     public void setPassword(String password) {
216     this.password=password;
217     }
218    
219     public void setDb(String db){
220     this.db=db;
221     }
222    
223     public void setKey(String key){
224     this.key=key;
225 duarte 34 setKeyTable();
226 duarte 15 setIdxColumn();
227     }
228    
229     public Statement createMasterStatement() {
230     Statement S=null;
231     try {
232     S=this.mCon.createStatement();
233     }
234     catch (SQLException e){
235 duarte 33 System.err.println("SQLException: " + e.getMessage());
236     System.err.println("SQLState: " + e.getSQLState());
237     System.err.println("Couldn't create statement for the master connection, exiting.");
238 duarte 15 System.exit(2);
239     }
240     return S;
241     }
242    
243     public ResultSet getAllIdxFromMaster(String key) {
244     this.setKey(key);
245     String query;
246     Statement S;
247     ResultSet R=null;
248     try {
249     query="SELECT "+idxColumn+" FROM "+keyTable+";";
250     S=this.mCon.createStatement();
251     R=S.executeQuery(query);
252     //S.close(); // apparently it doesn't work if we close the Statement!! Don't know why!
253     }
254     catch (SQLException e){
255 duarte 33 System.err.println("SQLException: " + e.getMessage());
256     System.err.println("SQLState: " + e.getSQLState());
257 duarte 34 System.err.println("Couldn't get all indices from columnn "+idxColumn+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
258 duarte 15 System.exit(2);
259     }
260     return R;
261     }
262 duarte 35 /**
263 duarte 38 * To get all ids and clients_names pairs for a certain key. Useful when need to submit to all hosts using qsub -q
264     * @param key the name of the key
265     * @return ResultSet with the pairs: id, client_name
266     */
267     public ResultSet getAllIdxAndClients (String key){
268     this.setKey(key);
269     String query;
270     Statement S;
271     ResultSet R = null;
272     try {
273     query="SELECT a."+idxColumn+",c.client_name FROM "+keyTable+" AS a INNER JOIN clients_names AS c ON (a.client_id=c.client_id);";
274     S=this.mCon.createStatement();
275     R=S.executeQuery(query);
276     //S.close(); // apparently it doesn't work if we close the Statement!! Don't know why!
277     }
278     catch (SQLException e){
279     System.err.println("SQLException: " + e.getMessage());
280     System.err.println("SQLState: " + e.getSQLState());
281     System.err.println("Couldn't get all indices/client_names pairs from table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
282     System.exit(2);
283     }
284     return R;
285     }
286    
287     /**
288 duarte 35 * To get client_id for a certain idx and key
289     * @param key the key name
290     * @param idx the id value for that key
291     * @return the client_id for node that has the data for the idx for that key
292     */
293 duarte 15 //TODO will need to change the query. In general this method would return more than 1 client_id if the idx is not unique
294     public int getHostId4Idx (String key,int idx) {
295     int hostId=0;
296     this.setKey(key);
297     Statement S;
298     ResultSet R;
299     String query;
300     int countCids=0;
301     try {
302     S=mCon.createStatement();
303     query="SELECT count(client_id) FROM "+keyTable+" WHERE "+idxColumn+"="+idx+";";
304     R=S.executeQuery(query);
305     if (R.next()){
306     countCids=R.getInt(1);
307     }
308     if (countCids!=1){
309 duarte 37 System.err.println("Error! the number of client_id for idx "+idxColumn+"= "+idx+" is 0 or bigger than 1." +
310     " The values where taken from host: "+MASTERHOST+", database: "+MASTERDB+", table: "+keyTable+". Check what's wrong! Exiting now.");
311 duarte 15 System.exit(2);
312     }
313     else {
314     query="SELECT client_id FROM "+keyTable+" WHERE "+idxColumn+"="+idx+";";
315     R=S.executeQuery(query);
316     if (R.next()){
317     hostId=R.getInt(1);
318     }
319     }
320     S.close();
321     R.close();
322     }
323     catch(SQLException e) {
324 duarte 33 System.err.println("Couldn't get the host id for idx "+idxColumn+"="+idx+", exiting");
325     System.err.println("SQLException: " + e.getMessage());
326     System.err.println("SQLState: " + e.getSQLState());
327 duarte 15 System.exit(3);
328     }
329     return hostId;
330     }
331    
332     public void insertIdxInMaster(String key, int clientId) {
333     Statement S;
334     String query;
335     this.setKey(key);
336     try {
337     S=this.mCon.createStatement();
338     query="INSERT INTO "+this.keyTable+" (client_id) VALUES ("+clientId+");";
339     S.executeUpdate(query);
340     S.close();
341     }
342     catch (SQLException E) {
343 duarte 33 System.err.println("SQLException: " + E.getMessage());
344     System.err.println("SQLState: " + E.getSQLState());
345 duarte 34 System.err.println("Couldn't insert new "+this.idxColumn+" in master table "+this.getKeyTable()+". The client_id for it was "+clientId+". Exiting.");
346 duarte 15 System.exit(2);
347     }
348     }
349    
350     public void insertIdxInMaster(String keySrc,String keyDest,int idxSrc) {
351     this.setKey(keySrc);
352     int clientId=0;
353     clientId=this.getHostId4Idx(keySrc,idxSrc);
354     insertIdxInMaster(keyDest,clientId);
355     }
356    
357     public int getLastInsertId(String key) {
358     int lastIdx=0;
359     this.setKey(key);
360     Statement S;
361     ResultSet R;
362     String query = "";
363     try {
364     S = this.mCon.createStatement();
365     query = "SELECT LAST_INSERT_ID() FROM "+this.keyTable+" LIMIT 1;";
366     R = S.executeQuery(query);
367     if (R.next()) {
368     lastIdx=R.getInt(1);
369     }
370     R.close();
371     S.close();
372     }
373     catch (SQLException E) {
374 duarte 33 System.err.println("Couldn't get the last insert id for key type "+this.idxColumn+" from table "+this.keyTable+". Exiting");
375     System.err.println("SQLException: " + E.getMessage());
376     System.err.println("SQLState: " + E.getSQLState());
377 duarte 15 System.exit(3);
378     } // end try/catch connection
379     return lastIdx;
380     } // end getGraphId
381 duarte 21
382     public int[][] getIdxSet(String key) {
383     int[][] indMatrix=null;
384     this.setKey(key);
385     String query;
386     Statement S;
387     ResultSet R;
388     try {
389     // STEP 1 -- getting set of all client_ids
390     S=this.mCon.createStatement();
391     query="SELECT count(distinct client_id) FROM "+keyTable+";";
392     int count=0;
393     R=S.executeQuery(query);
394     if (R.next()){
395     count=R.getInt(1);
396     }
397     query="SELECT DISTINCT client_id FROM "+keyTable+" ORDER BY client_id;";
398     //R.close();
399     //S.close();
400     R=S.executeQuery(query);
401    
402     // STEP 2 -- putting sets of indices counts into temp tables c_<client_id> with a serial auto_increment field
403     int[] clids=new int[count]; //array to store all client_ids. To be used in loops later
404     int i=0;
405     while (R.next()){
406     Statement Sloop=this.mCon.createStatement();
407     int clid=R.getInt(1);
408     query="CREATE TEMPORARY TABLE c_"+clid+" (serial int(11) NOT NULL AUTO_INCREMENT,"+idxColumn+" int(11),client_id int(11), PRIMARY KEY(serial));";
409     Sloop.executeUpdate(query);
410     query="INSERT INTO c_"+clid+" ("+idxColumn+",client_id) SELECT "+idxColumn+",client_id FROM "+keyTable+" WHERE client_id="+clid+";";
411     Sloop.executeUpdate(query);
412     clids[i]=clid;
413     i++;
414     Sloop.close();
415     }
416    
417     // STEP3 -- merging all c_<client_id> tables into a temp table tmp_allcs and selecting the client_id with the maximum count
418     //query="SELECT client_id,count(*) as c FROM c_34 GROUP BY client_id UNION SELECT client_id,count(*) as c FROM c_32 GROUP BY client_id;";
419     query="DROP TABLE IF EXISTS tmp_allcs;";
420     S.executeUpdate(query);
421     //this table must be permanent! otherwise cannot do the select max(c) later
422     query="CREATE TABLE IF NOT EXISTS tmp_allcs (client_id int(11), c int(11)) ENGINE=MEMORY;";
423     S.executeUpdate(query);
424     String unionStr="SELECT client_id,count(*) AS c FROM c_"+clids[0]+" GROUP BY client_id";
425     for (i=1;i<clids.length;i++) {
426     unionStr+=" UNION SELECT client_id,count(*) AS c FROM c_"+clids[i]+" GROUP BY client_id";
427     }
428     query="INSERT INTO tmp_allcs "+unionStr+";";
429     S.executeUpdate(query);
430     query="SELECT client_id,c FROM tmp_allcs WHERE c=(SELECT max(c) FROM tmp_allcs);";
431     R=S.executeQuery(query);
432     int clidMaxIdxCount=0;
433     int maxIdxCount=0;
434     if (R.next()) {
435     clidMaxIdxCount=R.getInt(1);
436     maxIdxCount=R.getInt(2);
437     }
438     query="DROP TABLE tmp_allcs;";
439     S.executeUpdate(query);
440    
441     // STEP 4 -- join all c_<client_id> tables into a table with a serial column, and c_<client_id> columns each of them with the indices for each client_id
442     //query="SELECT c_34.serial,c_34.asu_id AS c_34,c_32.asu_id AS c_32,c_36.asu_id AS c_36 FROM c_34 LEFT JOIN c_32 ON (c_34.serial=c_32.serial) LEFT JOIN c_36 ON (c_34.serial=c_36.serial);";
443     String selectStr="c_"+clidMaxIdxCount+".serial, c_"+clidMaxIdxCount+"."+idxColumn+" AS c_"+clidMaxIdxCount;
444     String fromStr="c_"+clidMaxIdxCount;
445     for (i=0;i<clids.length;i++) {
446     if (clids[i]!=clidMaxIdxCount){
447     selectStr+=", c_"+clids[i]+"."+idxColumn+" AS c_"+clids[i];
448     fromStr+=" LEFT JOIN c_"+clids[i]+" ON (c_"+clidMaxIdxCount+".serial=c_"+clids[i]+".serial)";
449     }
450     }
451     query="CREATE TEMPORARY TABLE indices_matrix "+"SELECT "+selectStr+" FROM "+fromStr+";";
452     S.executeUpdate(query);
453    
454     // STEP 5 -- put the table into a 2-dimensional array and return it
455     indMatrix = new int[maxIdxCount][clids.length];
456     query="SELECT * FROM indices_matrix";
457     R=S.executeQuery(query);
458     i=0;
459     while (R.next()) {
460     for (int j=0;j<clids.length;j++){
461 duarte 22 indMatrix[i][j]=R.getInt(j+2);
462 duarte 21 }
463     i++;
464     }
465     R.close();
466     S.close();
467     }
468     catch (SQLException e){
469 duarte 33 System.err.println("SQLException: " + e.getMessage());
470     System.err.println("SQLState: " + e.getSQLState());
471 duarte 34 System.err.println("Couldn't get the indices set from columnn "+idxColumn+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
472 duarte 21 System.exit(2);
473     }
474     return indMatrix;
475     }
476    
477    
478 duarte 15 }

Properties

Name Value
svn:executable *