ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tools/ClusterConnection.java
Revision: 81
Committed: Wed Apr 12 15:27:05 2006 UTC (18 years, 5 months ago) by duarte
File size: 14963 byte(s)
Log Message:
Changed the Connection fields to be MySQLConnection.
Thanks to this, simplify considerably a lot of the methods by using the MySQLConnection methods.
Got rid of method loadSQLDriver and URL final field
Line User Rev File contents
1 duarte 16 package tools;
2 duarte 15 import java.sql.*;
3 duarte 67 import java.util.ArrayList;
4     import java.util.HashMap;
5 duarte 15
6     /**
7     * ClusterConnection class to wrap the master/node mysql servers so that is transparent to other programs
8     * @author Jose Duarte
9     */
10    
11     public class ClusterConnection {
12    
13 duarte 34 private String MASTERDB="key_master";
14     private final String MASTERHOST="white";
15 duarte 81 private MySQLConnection nCon;
16     private MySQLConnection mCon;
17 duarte 15 public String keyTable;
18     public String key;
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 duarte 72 * @param key the key name: e.g. asu_id
28 duarte 35 * @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 72 setDb(db);
33     setUser(user);
34     setPassword(password);
35 duarte 81 // For nCon we create a connection to the master too.
36     // This is just a place holder because the actual node connection is not created until we create the statement
37     // 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
38     this.nCon = new MySQLConnection(MASTERHOST,user,password,MASTERDB);
39     this.mCon = new MySQLConnection(MASTERHOST,user,password,MASTERDB);
40 duarte 17 this.key=key; //can't use the setKey method here before we've got the db field initialized
41 duarte 34 setKeyTable(db);
42 duarte 15 }
43    
44 duarte 34 /**
45     * Create a ClusterConnection without passing a key. The key will be set later when we call createStatement(key,idx)
46 duarte 35 * @param db the database name
47     * @param user the user name for connection to both master and nodes
48     * @param password the password for connection to both master and nodes
49 duarte 34 */
50 duarte 15 public ClusterConnection (String db, String user,String password) {
51     setDb(db);
52     setUser(user);
53 duarte 81 setPassword(password);
54     // For nCon we create a connection to the master too.
55     // This is just a place holder because the actual node connection is not created until we create the statement
56     // 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
57     this.nCon = new MySQLConnection(MASTERHOST,user,password,MASTERDB);
58     this.mCon = new MySQLConnection(MASTERHOST,user,password,MASTERDB);
59 duarte 15 }
60    
61     public void close() {
62 duarte 81 this.nCon.close();
63     this.mCon.close();
64 duarte 15 }
65    
66     public String getHost4Idx (int idx) {
67     String host="";
68 duarte 81 String query = "SELECT client_name FROM "+keyTable+" AS m INNER JOIN clients_names AS c "+
69     "ON (m.client_id=c.client_id) WHERE "+key+"="+idx+";";
70     host=this.mCon.getStringFromDb(query);
71 duarte 15 return host;
72     }
73    
74     public void setHostFromIdx(int idx){
75     setHost(getHost4Idx(idx));
76     }
77    
78     public void setHost(String host) {
79     this.host=host;
80 duarte 81 //Closing previous connection is essential
81     //If we don't close it a lot of connections stay open after using a ClusterConnection object for a while
82     this.nCon.close();
83     this.nCon = new MySQLConnection(host,user,password,db);
84 duarte 15 }
85 duarte 35
86 duarte 34 /**
87     * This method is strictly private. We shouldn't call this from another class as a key might not be set when we call it
88     * and thus we can't get the client_id from the master key table. Only to be called from createStatement(key,idx)
89 duarte 35 * @param idx the value of the id for a certain key already set
90     * @return a Stament object with a connection to the node that contains idx for key
91 duarte 34 */
92     private Statement createStatement(int idx) { // to use when the field "key" is already set
93     setKeyTable();
94 duarte 15 Statement S=null;
95     this.setHostFromIdx(idx);
96     try {
97     S=this.nCon.createStatement();
98     }
99     catch (SQLException e){
100 duarte 33 System.err.println("SQLException: " + e.getMessage());
101     System.err.println("SQLState: " + e.getSQLState());
102     System.err.println("Couldn't create statement for the node connection, idx= "+idx+", exiting.");
103 duarte 15 System.exit(2);
104     }
105     return S;
106     }
107 duarte 35
108 duarte 34 /**
109 duarte 35 * This method is used to create a statement passing the key and idx. It will create a connection the the right node
110     * and return a Statement for that connection
111     * @param idx the key name
112     * @param idx the id value for that key
113     * @return a Statement object with a connection to the node that contains idx for key
114 duarte 34 */
115 duarte 15 public Statement createStatement(String key,int idx) {
116     setKey(key);
117     return createStatement(idx);
118     }
119    
120 duarte 35 /**
121 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
122     * @param query the SQL query
123     * @param key the name of the key
124     * @param idx the id value for that key
125     */
126 duarte 81 public void executeSql(String query,String key, int idx) throws SQLException {
127 duarte 43 Statement stmt;
128 duarte 81 stmt = this.createStatement(key,idx);
129     stmt.execute(query);
130     stmt.close();
131 duarte 43 }
132 duarte 81
133 duarte 51 /**
134     * To change the MASTERDB String, i.e. the name of the key master database. To be used in testing.
135     * @param db the name of the key master db we want to use instead of the default defined in the MASTERDB field
136     */
137     public void setKeyDb(String db) {
138     this.MASTERDB=db;
139 duarte 81 //Closing previous connection is essential
140     this.mCon.close();
141     this.mCon = new MySQLConnection(MASTERHOST,user,password,MASTERDB);
142 duarte 51 }
143 duarte 43
144     /**
145 duarte 72 * To set keyTable field in constructor (i.e. first time). Only to be used in constructor.
146 duarte 35 * @param db the database name
147     */
148     public void setKeyTable(String db) {
149 duarte 72 String query="SELECT key_master_table FROM dbs_keys WHERE db=\'"+db+"\' AND key_name=\'"+this.key+"\';";
150 duarte 81 this.keyTable=this.mCon.getStringFromDb(query);
151 duarte 15 }
152    
153 duarte 35 /**
154 duarte 43 * To set the keyTable field when db is already set
155 duarte 72 * The value of keyTable is taken from the dbs_keys table in the database given the db and key.
156 duarte 35 */
157     public void setKeyTable() {
158 duarte 72 String query="SELECT key_master_table FROM dbs_keys WHERE db=\'"+this.db+"\' AND key_name=\'"+this.key+"\';";
159 duarte 81 this.keyTable=this.mCon.getStringFromDb(query);
160 duarte 15 }
161    
162 duarte 34 public String getKeyTable() {
163 duarte 15 return this.keyTable;
164     }
165    
166 duarte 72 /**
167     * To get the name of the target table where splitted data is stored in nodes, e.g. for keyTable pdbgraph__asu_list, we get asu_list
168     * @return
169     */
170     public String getTableOnNode(){
171     String table="";
172     if (this.keyTable.contains("__")) {
173     String[] tokens=this.keyTable.split("__");
174     table=tokens[1];
175     }
176     else {
177     System.err.println("Error! The keyTable field is not set in this ClusterConnection object.");
178     }
179     return table;
180 duarte 15 }
181 duarte 72
182 duarte 15 public void setUser(String user) {
183     this.user=user;
184     }
185    
186     public void setPassword(String password) {
187     this.password=password;
188     }
189    
190     public void setDb(String db){
191     this.db=db;
192     }
193    
194     public void setKey(String key){
195     this.key=key;
196 duarte 34 setKeyTable();
197 duarte 15 }
198    
199     public Statement createMasterStatement() {
200     Statement S=null;
201     try {
202     S=this.mCon.createStatement();
203     }
204     catch (SQLException e){
205 duarte 33 System.err.println("SQLException: " + e.getMessage());
206     System.err.println("SQLState: " + e.getSQLState());
207     System.err.println("Couldn't create statement for the master connection, exiting.");
208 duarte 15 System.exit(2);
209     }
210     return S;
211     }
212 duarte 74
213 duarte 67 public int[] getAllIdxFromMaster(String key) {
214 duarte 15 this.setKey(key);
215 duarte 67 int[] ids=null;
216     ArrayList<Integer> idsAL=new ArrayList<Integer>();
217     try {
218 duarte 72 String query="SELECT "+key+" FROM "+keyTable+";";
219 duarte 67 Statement S=this.mCon.createStatement();
220     ResultSet R=S.executeQuery(query);
221     while (R.next()){
222     idsAL.add(R.getInt(1));
223     }
224     R.close();
225     S.close();
226 duarte 15 }
227     catch (SQLException e){
228 duarte 33 System.err.println("SQLException: " + e.getMessage());
229     System.err.println("SQLState: " + e.getSQLState());
230 duarte 72 System.err.println("Couldn't get all indices from columnn "+key+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
231 duarte 15 System.exit(2);
232     }
233 duarte 67 ids=new int[idsAL.size()];
234     for (int i=0;i<idsAL.size();i++){
235     ids[i]=idsAL.get(i);
236     }
237     return ids;
238 duarte 15 }
239 duarte 35 /**
240 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
241     * @param key the name of the key
242 duarte 67 * @return HashMap with keys = indices, and values = node names where the corresponding index is stored
243 duarte 38 */
244 duarte 67 public HashMap<Integer,String> getAllIdxAndClients (String key){
245 duarte 38 this.setKey(key);
246 duarte 67 HashMap<Integer,String> idsAndClients=new HashMap<Integer,String>();
247 duarte 38 try {
248 duarte 72 String query="SELECT a."+key+",c.client_name FROM "+keyTable+" AS a INNER JOIN clients_names AS c ON (a.client_id=c.client_id);";
249 duarte 67 Statement S=this.mCon.createStatement();
250     ResultSet R=S.executeQuery(query);
251     while (R.next()){
252     idsAndClients.put(R.getInt(1),R.getString(2));
253     }
254     R.close();
255     S.close();
256 duarte 38 }
257     catch (SQLException e){
258     System.err.println("SQLException: " + e.getMessage());
259     System.err.println("SQLState: " + e.getSQLState());
260     System.err.println("Couldn't get all indices/client_names pairs from table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
261     System.exit(2);
262     }
263 duarte 67 return idsAndClients;
264 duarte 38 }
265    
266     /**
267 duarte 35 * To get client_id for a certain idx and key
268     * @param key the key name
269     * @param idx the id value for that key
270     * @return the client_id for node that has the data for the idx for that key
271     */
272 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
273     public int getHostId4Idx (String key,int idx) {
274     int hostId=0;
275     this.setKey(key);
276     String query;
277     int countCids=0;
278 duarte 81 query="SELECT count(client_id) FROM "+keyTable+" WHERE "+key+"="+idx+";";
279     countCids=this.mCon.getIntFromDb(query);
280     if (countCids!=1){
281     System.err.println("the query was: "+query);
282     System.err.println("Error! the count of client_ids for idx "+key+"= "+idx+" is " +countCids+
283     ". It must be 1! The values were taken from host: "+MASTERHOST+", database: "+MASTERDB+", table: "+keyTable+". Check what's wrong! Exiting now.");
284     System.exit(2);
285 duarte 15 }
286 duarte 81 else {
287     query="SELECT client_id FROM "+keyTable+" WHERE "+key+"="+idx+";";
288     hostId=this.mCon.getIntFromDb(query);
289 duarte 15 }
290     return hostId;
291     }
292    
293     public void insertIdxInMaster(String key, int clientId) {
294     String query;
295     this.setKey(key);
296     try {
297     query="INSERT INTO "+this.keyTable+" (client_id) VALUES ("+clientId+");";
298 duarte 81 this.mCon.executeSql(query);
299 duarte 15 }
300     catch (SQLException E) {
301 duarte 33 System.err.println("SQLException: " + E.getMessage());
302     System.err.println("SQLState: " + E.getSQLState());
303 duarte 72 System.err.println("Couldn't insert new "+this.key+" in master table "+this.getKeyTable()+". The client_id for it was "+clientId+". Exiting.");
304 duarte 15 System.exit(2);
305     }
306     }
307    
308     public void insertIdxInMaster(String keySrc,String keyDest,int idxSrc) {
309     this.setKey(keySrc);
310     int clientId=0;
311     clientId=this.getHostId4Idx(keySrc,idxSrc);
312     insertIdxInMaster(keyDest,clientId);
313     }
314    
315     public int getLastInsertId(String key) {
316     int lastIdx=0;
317     this.setKey(key);
318     String query = "";
319 duarte 81 query = "SELECT LAST_INSERT_ID() FROM "+this.keyTable+" LIMIT 1;";
320     lastIdx=this.mCon.getIntFromDb(query);
321 duarte 15 return lastIdx;
322 duarte 81 }
323 duarte 21
324     public int[][] getIdxSet(String key) {
325     int[][] indMatrix=null;
326     this.setKey(key);
327     String query;
328     Statement S;
329     ResultSet R;
330     try {
331 duarte 81 // STEP 1 -- getting set of all client_ids
332 duarte 21 query="SELECT count(distinct client_id) FROM "+keyTable+";";
333     int count=0;
334 duarte 81 count=this.mCon.getIntFromDb(query);
335     S=this.mCon.createStatement();
336 duarte 21 query="SELECT DISTINCT client_id FROM "+keyTable+" ORDER BY client_id;";
337     R=S.executeQuery(query);
338    
339     // STEP 2 -- putting sets of indices counts into temp tables c_<client_id> with a serial auto_increment field
340     int[] clids=new int[count]; //array to store all client_ids. To be used in loops later
341     int i=0;
342     while (R.next()){
343     Statement Sloop=this.mCon.createStatement();
344     int clid=R.getInt(1);
345 duarte 72 query="CREATE TEMPORARY TABLE c_"+clid+" (serial int(11) NOT NULL AUTO_INCREMENT,"+key+" int(11),client_id int(11), PRIMARY KEY(serial));";
346 duarte 21 Sloop.executeUpdate(query);
347 duarte 72 query="INSERT INTO c_"+clid+" ("+key+",client_id) SELECT "+key+",client_id FROM "+keyTable+" WHERE client_id="+clid+";";
348 duarte 21 Sloop.executeUpdate(query);
349     clids[i]=clid;
350     i++;
351     Sloop.close();
352     }
353    
354     // STEP3 -- merging all c_<client_id> tables into a temp table tmp_allcs and selecting the client_id with the maximum count
355     //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;";
356     query="DROP TABLE IF EXISTS tmp_allcs;";
357     S.executeUpdate(query);
358     //this table must be permanent! otherwise cannot do the select max(c) later
359     query="CREATE TABLE IF NOT EXISTS tmp_allcs (client_id int(11), c int(11)) ENGINE=MEMORY;";
360     S.executeUpdate(query);
361     String unionStr="SELECT client_id,count(*) AS c FROM c_"+clids[0]+" GROUP BY client_id";
362     for (i=1;i<clids.length;i++) {
363     unionStr+=" UNION SELECT client_id,count(*) AS c FROM c_"+clids[i]+" GROUP BY client_id";
364     }
365     query="INSERT INTO tmp_allcs "+unionStr+";";
366     S.executeUpdate(query);
367     query="SELECT client_id,c FROM tmp_allcs WHERE c=(SELECT max(c) FROM tmp_allcs);";
368     R=S.executeQuery(query);
369     int clidMaxIdxCount=0;
370     int maxIdxCount=0;
371     if (R.next()) {
372     clidMaxIdxCount=R.getInt(1);
373     maxIdxCount=R.getInt(2);
374     }
375     query="DROP TABLE tmp_allcs;";
376     S.executeUpdate(query);
377    
378     // 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
379     //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);";
380 duarte 72 String selectStr="c_"+clidMaxIdxCount+".serial, c_"+clidMaxIdxCount+"."+key+" AS c_"+clidMaxIdxCount;
381 duarte 21 String fromStr="c_"+clidMaxIdxCount;
382     for (i=0;i<clids.length;i++) {
383     if (clids[i]!=clidMaxIdxCount){
384 duarte 72 selectStr+=", c_"+clids[i]+"."+key+" AS c_"+clids[i];
385 duarte 21 fromStr+=" LEFT JOIN c_"+clids[i]+" ON (c_"+clidMaxIdxCount+".serial=c_"+clids[i]+".serial)";
386     }
387     }
388     query="CREATE TEMPORARY TABLE indices_matrix "+"SELECT "+selectStr+" FROM "+fromStr+";";
389     S.executeUpdate(query);
390    
391     // STEP 5 -- put the table into a 2-dimensional array and return it
392     indMatrix = new int[maxIdxCount][clids.length];
393     query="SELECT * FROM indices_matrix";
394     R=S.executeQuery(query);
395     i=0;
396     while (R.next()) {
397     for (int j=0;j<clids.length;j++){
398 duarte 22 indMatrix[i][j]=R.getInt(j+2);
399 duarte 21 }
400     i++;
401     }
402     R.close();
403     S.close();
404     }
405     catch (SQLException e){
406 duarte 33 System.err.println("SQLException: " + e.getMessage());
407     System.err.println("SQLState: " + e.getSQLState());
408 duarte 72 System.err.println("Couldn't get the indices set from columnn "+key+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
409 duarte 21 System.exit(2);
410     }
411     return indMatrix;
412     }
413    
414    
415 duarte 15 }

Properties

Name Value
svn:executable *