KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > controller > loadbalancer > tasks > ReadStoredProcedureTask


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): ______________________.
23  */

24
25 package org.objectweb.cjdbc.controller.loadbalancer.tasks;
26
27 import java.sql.Connection JavaDoc;
28 import java.sql.SQLException JavaDoc;
29
30 import org.objectweb.cjdbc.common.exceptions.NoTransactionStartWhenDisablingException;
31 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
32 import org.objectweb.cjdbc.common.log.Trace;
33 import org.objectweb.cjdbc.common.sql.StoredProcedure;
34 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
35 import org.objectweb.cjdbc.controller.cache.metadata.MetadataCache;
36 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager;
37 import org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer;
38 import org.objectweb.cjdbc.controller.loadbalancer.BackendWorkerThread;
39 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
40
41 /**
42  * Executes a <code>StoredProcedure</code> call that returns a ResultSet.
43  *
44  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
45  * @version 1.0
46  */

47 public class ReadStoredProcedureTask extends AbstractTask
48 {
49   private StoredProcedure proc;
50   private ControllerResultSet result;
51   private MetadataCache metadataCache;
52
53   /**
54    * Creates a new <code>ReadStoredProcedureTask</code>.
55    *
56    * @param nbToComplete number of threads that must succeed before returning
57    * @param totalNb total number of threads
58    * @param proc the <code>StoredProcedure</code> to call
59    * @param metadataCache the metadataCache if any or null
60    */

61   public ReadStoredProcedureTask(int nbToComplete, int totalNb,
62       StoredProcedure proc, MetadataCache metadataCache)
63   {
64     super(nbToComplete, totalNb);
65     this.proc = proc;
66     this.metadataCache = metadataCache;
67   }
68
69   /**
70    * Call a stored procedure that returns a ResultSet on the given backend
71    * thread.
72    *
73    * @param backendThread the backend thread that will execute the task
74    * @throws SQLException if an error occurs
75    */

76   public void executeTask(BackendWorkerThread backendThread)
77       throws SQLException JavaDoc
78   {
79     DatabaseBackend backend = backendThread.getBackend();
80
81     AbstractConnectionManager cm = backend
82         .getConnectionManager(proc.getLogin());
83     if (cm == null)
84     {
85       SQLException JavaDoc se = new SQLException JavaDoc(
86           "No Connection Manager for Virtual Login:" + proc.getLogin());
87       try
88       {
89         notifyFailure(backendThread, 1, se);
90       }
91       catch (SQLException JavaDoc ignore)
92       {
93
94       }
95       throw se;
96     }
97
98     Trace logger = backendThread.getLogger();
99     if (proc.isAutoCommit())
100     { // Use a connection just for this request
101
Connection JavaDoc c = null;
102       try
103       {
104         c = cm.getConnection();
105       }
106       catch (UnreachableBackendException e1)
107       {
108         SQLException JavaDoc se = new SQLException JavaDoc("Backend " + backend.getName()
109             + " is no more reachable.");
110         try
111         {
112           notifyFailure(backendThread, 1, se);
113         }
114         catch (SQLException JavaDoc ignore)
115         {
116         }
117         // Disable this backend (it is no more in sync) by killing the backend
118
// thread
119
backendThread.kill();
120         logger.error("Disabling backend " + backend.getName()
121             + " because it is no more reachable.");
122         throw se;
123       }
124
125       // Sanity check
126
if (c == null)
127       {
128         SQLException JavaDoc se = new SQLException JavaDoc("No more connections");
129         try
130         { // All backends failed, just ignore
131
if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
132             return;
133         }
134         catch (SQLException JavaDoc ignore)
135         {
136         }
137         // Disable this backend (it is no more in sync) by killing the backend
138
// thread
139
backendThread.kill();
140         String JavaDoc msg = "Stored procedure '"
141             + proc.getSQLShortForm(backend.getSQLShortFormLength())
142             + "' failed on backend " + backend.getName() + " but "
143             + getSuccess() + " succeeded (" + se + ")";
144         logger.error(msg);
145         throw new SQLException JavaDoc(msg);
146       }
147
148       // Execute Query
149
try
150       {
151         result = AbstractLoadBalancer.executeReadStoredProcedureOnBackend(proc,
152             backend, c, metadataCache);
153         
154         backend.setSchemaIsDirty(true);
155       }
156       catch (Exception JavaDoc e)
157       {
158         try
159         { // All backends failed, just ignore
160
if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, e))
161             return;
162         }
163         catch (SQLException JavaDoc ignore)
164         {
165         }
166         // Disable this backend (it is no more in sync) by killing the backend
167
// thread
168
backendThread.kill();
169         String JavaDoc msg = "Stored procedure '"
170             + proc.getSQLShortForm(backend.getSQLShortFormLength())
171             + "' failed on backend " + backend.getName() + " but "
172             + getSuccess() + " succeeded (" + e + ")";
173         logger.error(msg);
174         throw new SQLException JavaDoc(msg);
175       }
176       finally
177       {
178         cm.releaseConnection(c);
179       }
180     }
181     else
182     { // Re-use the connection used by this transaction
183
Connection JavaDoc c;
184       long tid = proc.getTransactionId();
185       Long JavaDoc lTid = new Long JavaDoc(tid);
186
187       try
188       {
189         c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(lTid, cm,
190             proc.getTransactionIsolation());
191       }
192       catch (UnreachableBackendException ube)
193       {
194         SQLException JavaDoc se = new SQLException JavaDoc("Backend " + backend.getName()
195             + " is no more reachable.");
196         try
197         {
198           notifyFailure(backendThread, 1, se);
199         }
200         catch (SQLException JavaDoc ignore)
201         {
202         }
203         // Disable this backend (it is no more in sync) by killing the backend
204
// thread
205
backendThread.kill();
206         logger.error("Disabling backend " + backend.getName()
207             + " because it is no more reachable.");
208         throw se;
209       }
210       catch (NoTransactionStartWhenDisablingException e)
211       {
212         logger
213             .error("Disabling backend "
214                 + backend.getName()
215                 + " has been assigned a select request but it cannot start a new transaction for it.");
216         notifyFailure(backendThread, (long) proc.getTimeout() * 1000, e);
217         return;
218       }
219       catch (SQLException JavaDoc e1)
220       {
221         SQLException JavaDoc se = new SQLException JavaDoc(
222             "Unable to get connection for transaction " + tid);
223         try
224         { // All backends failed, just ignore
225
if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
226             return;
227         }
228         catch (SQLException JavaDoc ignore)
229         {
230         }
231         // Disable this backend (it is no more in sync) by killing the
232
// backend thread
233
backendThread.kill();
234         String JavaDoc msg = "Request '"
235             + proc.getSQLShortForm(backend.getSQLShortFormLength())
236             + "' failed on backend " + backend.getName() + " but "
237             + getSuccess() + " succeeded (" + se + ")";
238         logger.error(msg);
239         throw new SQLException JavaDoc(msg);
240       }
241
242       // Sanity check
243
if (c == null)
244       { // Bad connection
245
SQLException JavaDoc se = new SQLException JavaDoc(
246             "Unable to retrieve connection for transaction " + tid);
247         try
248         { // All backends failed, just ignore
249
if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
250             return;
251         }
252         catch (SQLException JavaDoc ignore)
253         {
254         }
255         // Disable this backend (it is no more in sync) by killing the
256
// backend thread
257
backendThread.kill();
258         String JavaDoc msg = "Request '"
259             + proc.getSQLShortForm(backend.getSQLShortFormLength())
260             + "' failed on backend " + backend.getName() + " but "
261             + getSuccess() + " succeeded (" + se + ")";
262         logger.error(msg);
263         throw new SQLException JavaDoc(msg);
264       }
265
266       // Execute Query
267
try
268       {
269         result = AbstractLoadBalancer.executeReadStoredProcedureOnBackend(proc,
270             backend, c, metadataCache);
271
272         backend.setSchemaIsDirty(true);
273       }
274       catch (Exception JavaDoc e)
275       {
276         try
277         { // All backends failed, just ignore
278
if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, e))
279             return;
280         }
281         catch (SQLException JavaDoc ignore)
282         {
283         }
284         // Disable this backend (it is no more in sync) by killing the backend
285
// thread
286
backendThread.kill();
287         String JavaDoc msg = "Stored procedure '"
288             + proc.getSQLShortForm(backend.getSQLShortFormLength())
289             + "' failed on backend " + backend.getName() + " but "
290             + getSuccess() + " succeeded (" + e + ")";
291         logger.error(msg);
292         throw new SQLException JavaDoc(msg);
293       }
294     }
295     notifySuccess();
296   }
297
298   /**
299    * Returns the result.
300    *
301    * @return a <code>ResultSet</code>
302    */

303   public ControllerResultSet getResult()
304   {
305     return result;
306   }
307
308   /**
309    * @see java.lang.Object#toString()
310    */

311   public String JavaDoc toString()
312   {
313     return "ReadStoredProcedureTask (" + proc.getSQL() + ")";
314   }
315 }
Popular Tags