ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tools/ClusterConnection.java
Revision: 37
Committed: Fri Mar 17 11:22:19 2006 UTC (18 years, 6 months ago) by duarte
File size: 14593 byte(s)
Log Message:
Some changes in error messages to be more clear.
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     * To set keyTable field in constructor (i.e. first time)
169     * @param db the database name
170     */
171     public void setKeyTable(String db) {
172 duarte 15 this.keyTable=db+"_"+this.key+"_list_master";
173     }
174    
175 duarte 35 /**
176     * To se the keyTable field when db is already set
177     *
178     */
179     public void setKeyTable() {
180 duarte 15 this.keyTable=this.db+"_"+this.key+"_list_master";
181     }
182    
183 duarte 34 public String getKeyTable() {
184 duarte 15 return this.keyTable;
185     }
186    
187     public void setIdxColumn() {
188     this.idxColumn=this.key+"_id";
189     }
190    
191     public void setUser(String user) {
192     this.user=user;
193     }
194    
195     public void setPassword(String password) {
196     this.password=password;
197     }
198    
199     public void setDb(String db){
200     this.db=db;
201     }
202    
203     public void setKey(String key){
204     this.key=key;
205 duarte 34 setKeyTable();
206 duarte 15 setIdxColumn();
207     }
208    
209     public Statement createMasterStatement() {
210     Statement S=null;
211     try {
212     S=this.mCon.createStatement();
213     }
214     catch (SQLException e){
215 duarte 33 System.err.println("SQLException: " + e.getMessage());
216     System.err.println("SQLState: " + e.getSQLState());
217     System.err.println("Couldn't create statement for the master connection, exiting.");
218 duarte 15 System.exit(2);
219     }
220     return S;
221     }
222    
223     public ResultSet getAllIdxFromMaster(String key) {
224     this.setKey(key);
225     String query;
226     Statement S;
227     ResultSet R=null;
228     try {
229     query="SELECT "+idxColumn+" FROM "+keyTable+";";
230     S=this.mCon.createStatement();
231     R=S.executeQuery(query);
232     //S.close(); // apparently it doesn't work if we close the Statement!! Don't know why!
233     }
234     catch (SQLException e){
235 duarte 33 System.err.println("SQLException: " + e.getMessage());
236     System.err.println("SQLState: " + e.getSQLState());
237 duarte 34 System.err.println("Couldn't get all indices from columnn "+idxColumn+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
238 duarte 15 System.exit(2);
239     }
240     return R;
241     }
242    
243 duarte 35 /**
244     * To get client_id for a certain idx and key
245     * @param key the key name
246     * @param idx the id value for that key
247     * @return the client_id for node that has the data for the idx for that key
248     */
249 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
250     public int getHostId4Idx (String key,int idx) {
251     int hostId=0;
252     this.setKey(key);
253     Statement S;
254     ResultSet R;
255     String query;
256     int countCids=0;
257     try {
258     S=mCon.createStatement();
259     query="SELECT count(client_id) FROM "+keyTable+" WHERE "+idxColumn+"="+idx+";";
260     R=S.executeQuery(query);
261     if (R.next()){
262     countCids=R.getInt(1);
263     }
264     if (countCids!=1){
265 duarte 37 System.err.println("Error! the number of client_id for idx "+idxColumn+"= "+idx+" is 0 or bigger than 1." +
266     " The values where taken from host: "+MASTERHOST+", database: "+MASTERDB+", table: "+keyTable+". Check what's wrong! Exiting now.");
267 duarte 15 System.exit(2);
268     }
269     else {
270     query="SELECT client_id FROM "+keyTable+" WHERE "+idxColumn+"="+idx+";";
271     R=S.executeQuery(query);
272     if (R.next()){
273     hostId=R.getInt(1);
274     }
275     }
276     S.close();
277     R.close();
278     }
279     catch(SQLException e) {
280 duarte 33 System.err.println("Couldn't get the host id for idx "+idxColumn+"="+idx+", exiting");
281     System.err.println("SQLException: " + e.getMessage());
282     System.err.println("SQLState: " + e.getSQLState());
283 duarte 15 System.exit(3);
284     }
285     return hostId;
286     }
287    
288     public void insertIdxInMaster(String key, int clientId) {
289     Statement S;
290     String query;
291     this.setKey(key);
292     try {
293     S=this.mCon.createStatement();
294     query="INSERT INTO "+this.keyTable+" (client_id) VALUES ("+clientId+");";
295     S.executeUpdate(query);
296     S.close();
297     }
298     catch (SQLException E) {
299 duarte 33 System.err.println("SQLException: " + E.getMessage());
300     System.err.println("SQLState: " + E.getSQLState());
301 duarte 34 System.err.println("Couldn't insert new "+this.idxColumn+" in master table "+this.getKeyTable()+". The client_id for it was "+clientId+". Exiting.");
302 duarte 15 System.exit(2);
303     }
304     }
305    
306     public void insertIdxInMaster(String keySrc,String keyDest,int idxSrc) {
307     this.setKey(keySrc);
308     int clientId=0;
309     clientId=this.getHostId4Idx(keySrc,idxSrc);
310     insertIdxInMaster(keyDest,clientId);
311     }
312    
313     public int getLastInsertId(String key) {
314     int lastIdx=0;
315     this.setKey(key);
316     Statement S;
317     ResultSet R;
318     String query = "";
319     try {
320     S = this.mCon.createStatement();
321     query = "SELECT LAST_INSERT_ID() FROM "+this.keyTable+" LIMIT 1;";
322     R = S.executeQuery(query);
323     if (R.next()) {
324     lastIdx=R.getInt(1);
325     }
326     R.close();
327     S.close();
328     }
329     catch (SQLException E) {
330 duarte 33 System.err.println("Couldn't get the last insert id for key type "+this.idxColumn+" from table "+this.keyTable+". Exiting");
331     System.err.println("SQLException: " + E.getMessage());
332     System.err.println("SQLState: " + E.getSQLState());
333 duarte 15 System.exit(3);
334     } // end try/catch connection
335     return lastIdx;
336     } // end getGraphId
337 duarte 21
338     public int[][] getIdxSet(String key) {
339     int[][] indMatrix=null;
340     this.setKey(key);
341     String query;
342     Statement S;
343     ResultSet R;
344     try {
345     // STEP 1 -- getting set of all client_ids
346     S=this.mCon.createStatement();
347     query="SELECT count(distinct client_id) FROM "+keyTable+";";
348     int count=0;
349     R=S.executeQuery(query);
350     if (R.next()){
351     count=R.getInt(1);
352     }
353     query="SELECT DISTINCT client_id FROM "+keyTable+" ORDER BY client_id;";
354     //R.close();
355     //S.close();
356     R=S.executeQuery(query);
357    
358     // STEP 2 -- putting sets of indices counts into temp tables c_<client_id> with a serial auto_increment field
359     int[] clids=new int[count]; //array to store all client_ids. To be used in loops later
360     int i=0;
361     while (R.next()){
362     Statement Sloop=this.mCon.createStatement();
363     int clid=R.getInt(1);
364     query="CREATE TEMPORARY TABLE c_"+clid+" (serial int(11) NOT NULL AUTO_INCREMENT,"+idxColumn+" int(11),client_id int(11), PRIMARY KEY(serial));";
365     Sloop.executeUpdate(query);
366     query="INSERT INTO c_"+clid+" ("+idxColumn+",client_id) SELECT "+idxColumn+",client_id FROM "+keyTable+" WHERE client_id="+clid+";";
367     Sloop.executeUpdate(query);
368     clids[i]=clid;
369     i++;
370     Sloop.close();
371     }
372    
373     // STEP3 -- merging all c_<client_id> tables into a temp table tmp_allcs and selecting the client_id with the maximum count
374     //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;";
375     query="DROP TABLE IF EXISTS tmp_allcs;";
376     S.executeUpdate(query);
377     //this table must be permanent! otherwise cannot do the select max(c) later
378     query="CREATE TABLE IF NOT EXISTS tmp_allcs (client_id int(11), c int(11)) ENGINE=MEMORY;";
379     S.executeUpdate(query);
380     String unionStr="SELECT client_id,count(*) AS c FROM c_"+clids[0]+" GROUP BY client_id";
381     for (i=1;i<clids.length;i++) {
382     unionStr+=" UNION SELECT client_id,count(*) AS c FROM c_"+clids[i]+" GROUP BY client_id";
383     }
384     query="INSERT INTO tmp_allcs "+unionStr+";";
385     S.executeUpdate(query);
386     query="SELECT client_id,c FROM tmp_allcs WHERE c=(SELECT max(c) FROM tmp_allcs);";
387     R=S.executeQuery(query);
388     int clidMaxIdxCount=0;
389     int maxIdxCount=0;
390     if (R.next()) {
391     clidMaxIdxCount=R.getInt(1);
392     maxIdxCount=R.getInt(2);
393     }
394     query="DROP TABLE tmp_allcs;";
395     S.executeUpdate(query);
396    
397     // 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
398     //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);";
399     String selectStr="c_"+clidMaxIdxCount+".serial, c_"+clidMaxIdxCount+"."+idxColumn+" AS c_"+clidMaxIdxCount;
400     String fromStr="c_"+clidMaxIdxCount;
401     for (i=0;i<clids.length;i++) {
402     if (clids[i]!=clidMaxIdxCount){
403     selectStr+=", c_"+clids[i]+"."+idxColumn+" AS c_"+clids[i];
404     fromStr+=" LEFT JOIN c_"+clids[i]+" ON (c_"+clidMaxIdxCount+".serial=c_"+clids[i]+".serial)";
405     }
406     }
407     query="CREATE TEMPORARY TABLE indices_matrix "+"SELECT "+selectStr+" FROM "+fromStr+";";
408     S.executeUpdate(query);
409    
410     // STEP 5 -- put the table into a 2-dimensional array and return it
411     indMatrix = new int[maxIdxCount][clids.length];
412     query="SELECT * FROM indices_matrix";
413     R=S.executeQuery(query);
414     i=0;
415     while (R.next()) {
416     for (int j=0;j<clids.length;j++){
417 duarte 22 indMatrix[i][j]=R.getInt(j+2);
418 duarte 21 }
419     i++;
420     }
421     R.close();
422     S.close();
423     }
424     catch (SQLException e){
425 duarte 33 System.err.println("SQLException: " + e.getMessage());
426     System.err.println("SQLState: " + e.getSQLState());
427 duarte 34 System.err.println("Couldn't get the indices set from columnn "+idxColumn+" in table "+keyTable+" from "+MASTERDB+" database in "+MASTERHOST+", exiting.");
428 duarte 21 System.exit(2);
429     }
430     return indMatrix;
431     }
432    
433    
434 duarte 15 }

Properties

Name Value
svn:executable *