KickJava   Java API By Example, From Geeks To Geeks.

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


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): Jaco Swart.
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.i18n.Translate;
33 import org.objectweb.cjdbc.common.log.Trace;
34 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
35 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
36 import org.objectweb.cjdbc.controller.cache.metadata.MetadataCache;
37 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager;
38 import org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer;
39 import org.objectweb.cjdbc.controller.loadbalancer.BackendWorkerThread;
40 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
41
42 /**
43  * Executes a <code>AbstractWriteRequest</code> statement and return the auto
44  * generated keys.
45  *
46  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
47  * @author <a HREF="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
48  * @version 1.0
49  */

50 public class WriteRequestWithKeysTask extends AbstractTask
51 {
52   private AbstractWriteRequest request;
53   private ControllerResultSet result;
54   private MetadataCache metadataCache;
55
56   /**
57    * Creates a new <code>WriteRequestTask</code>.
58    *
59    * @param nbToComplete number of threads that must succeed before returning
60    * @param totalNb total number of threads
61    * @param request an <code>AbstractWriteRequest</code>
62    * @param metadataCache the metadataCache if any or null
63    */

64   public WriteRequestWithKeysTask(int nbToComplete, int totalNb,
65       AbstractWriteRequest request, MetadataCache metadataCache)
66   {
67     super(nbToComplete, totalNb);
68     this.request = request;
69     this.metadataCache = metadataCache;
70   }
71
72   /**
73    * Executes a write request with the given backend thread.
74    *
75    * @param backendThread the backend thread that will execute the task
76    * @throws SQLException if an error occurs
77    */

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

323   public ControllerResultSet getResult()
324   {
325     return result;
326   }
327
328   /**
329    * @see java.lang.Object#toString()
330    */

331   public String JavaDoc toString()
332   {
333     if (request.isAutoCommit())
334       return "WriteWithKeys Autocommit Task (" + request.getSQL() + ")";
335     else
336       return "WriteWithKeys Task from transaction:"
337           + request.getTransactionId() + "(" + request.getSQL() + ")";
338   }
339
340 }
Popular Tags