Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

WriteStoredProcedureTask.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet.
00022  * Contributor(s): ______________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.loadbalancer.tasks;
00026 
00027 import java.sql.Connection;
00028 import java.sql.SQLException;
00029 
00030 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
00031 import org.objectweb.cjdbc.common.log.Trace;
00032 import org.objectweb.cjdbc.common.sql.StoredProcedure;
00033 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00034 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager;
00035 import org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer;
00036 import org.objectweb.cjdbc.controller.loadbalancer.BackendWorkerThread;
00037 
00038 /**
00039  * Executes a write <code>StoredProcedure</code> call.
00040  * 
00041  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00042  * @version 1.0
00043  */
00044 public class WriteStoredProcedureTask extends AbstractTask
00045 {
00046   private StoredProcedure proc;
00047   private int             result;
00048 
00049   /**
00050    * Creates a new <code>WriteStoredProcedureTask</code>.
00051    * 
00052    * @param nbToComplete number of threads that must succeed before returning
00053    * @param totalNb total number of threads
00054    * @param proc the <code>StoredProcedure</code> to call
00055    */
00056   public WriteStoredProcedureTask(int nbToComplete, int totalNb,
00057       StoredProcedure proc)
00058   {
00059     super(nbToComplete, totalNb);
00060     this.proc = proc;
00061   }
00062 
00063   /**
00064    * Executes a write request with the given backend thread.
00065    * 
00066    * @param backendThread the backend thread that will execute the task
00067    * @throws SQLException if an error occurs
00068    */
00069   public void executeTask(BackendWorkerThread backendThread)
00070       throws SQLException
00071   {
00072     DatabaseBackend backend = backendThread.getBackend();
00073 
00074     AbstractConnectionManager cm = backend
00075         .getConnectionManager(proc.getLogin());
00076     if (cm == null)
00077     {
00078       SQLException se = new SQLException(
00079           "No Connection Manager for Virtual Login:" + proc.getLogin());
00080       try
00081       {
00082         notifyFailure(backendThread, 1, se);
00083       }
00084       catch (SQLException ignore)
00085       {
00086 
00087       }
00088       throw se;
00089     }
00090 
00091     Trace logger = backendThread.getLogger();
00092     if (proc.isAutoCommit())
00093     {
00094       if (backend.isDisabling())
00095       {
00096         // Backend is disabling, we do not execute queries except the one in the
00097         // transaction we already started. Just notify the completion for the
00098         // others.
00099         notifyCompletion();
00100         return;
00101       }
00102 
00103       // Use a connection just for this request
00104       Connection c = null;
00105       try
00106       {
00107         c = cm.getConnection();
00108       }
00109       catch (UnreachableBackendException e1)
00110       {
00111         SQLException se = new SQLException("Backend " + backend.getName()
00112             + " is no more reachable.");
00113         try
00114         {
00115           notifyFailure(backendThread, 1, se);
00116         }
00117         catch (SQLException ignore)
00118         {
00119         }
00120         // Disable this backend (it is no more in sync) by killing the backend
00121         // thread
00122         backendThread.kill();
00123         logger.error("Disabling backend " + backend.getName()
00124             + " because it is no more reachable.");
00125         throw se;
00126       }
00127 
00128       // Sanity check
00129       if (c == null)
00130       {
00131         SQLException se = new SQLException("No more connections");
00132         try
00133         { // All backends failed, just ignore
00134           if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
00135             return;
00136         }
00137         catch (SQLException ignore)
00138         {
00139         }
00140         // Disable this backend (it is no more in sync) by killing the backend
00141         // thread
00142         backendThread.kill();
00143         String msg = "Stored procedure '"
00144             + proc.getSQLShortForm(backend.getSQLShortFormLength())
00145             + "' failed on backend " + backend.getName() + " but "
00146             + getSuccess() + " succeeded (" + se + ")";
00147         logger.error(msg);
00148         throw new SQLException(msg);
00149       }
00150 
00151       // Execute Query
00152       try
00153       {
00154         result = AbstractLoadBalancer.executeWriteStoredProcedureOnBackend(
00155             proc, backend, c);
00156 
00157         // Warning! No way to detect if schema has been modified unless
00158         // we ask the backend again using DatabaseMetaData.getTables().
00159       }
00160       catch (Exception e)
00161       {
00162         try
00163         { // All backends failed, just ignore
00164           if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, e))
00165             return;
00166         }
00167         catch (SQLException ignore)
00168         {
00169         }
00170         // Disable this backend (it is no more in sync) by killing the backend
00171         // thread
00172         backendThread.kill();
00173         String msg = "Stored procedure '"
00174             + proc.getSQLShortForm(backend.getSQLShortFormLength())
00175             + "' failed on backend " + backend.getName() + " but "
00176             + getSuccess() + " succeeded (" + e + ")";
00177         logger.error(msg);
00178         throw new SQLException(msg);
00179       }
00180       finally
00181       {
00182         cm.releaseConnection(c);
00183       }
00184     }
00185     else
00186     { // Re-use the connection used by this transaction
00187       Connection c;
00188       long tid = proc.getTransactionId();
00189       Long lTid = new Long(tid);
00190 
00191       try
00192       {
00193         c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(lTid, cm);
00194       }
00195       catch (UnreachableBackendException ube)
00196       {
00197         SQLException se = new SQLException("Backend " + backend.getName()
00198             + " is no more reachable.");
00199         try
00200         {
00201           notifyFailure(backendThread, 1, se);
00202         }
00203         catch (SQLException ignore)
00204         {
00205         }
00206         // Disable this backend (it is no more in sync) by killing the backend
00207         // thread
00208         backendThread.kill();
00209         logger.error("Disabling backend " + backend.getName()
00210             + " because it is no more reachable.");
00211         throw se;
00212       }
00213       catch (SQLException e1)
00214       {
00215         SQLException se = new SQLException(
00216             "Unable to get connection for transaction " + tid);
00217         try
00218         { // All backends failed, just ignore
00219           if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
00220             return;
00221         }
00222         catch (SQLException ignore)
00223         {
00224         }
00225         // Disable this backend (it is no more in sync) by killing the
00226         // backend thread
00227         backendThread.kill();
00228         String msg = "Request '"
00229             + proc.getSQLShortForm(backend.getSQLShortFormLength())
00230             + "' failed on backend " + backend.getName() + " but "
00231             + getSuccess() + " succeeded (" + se + ")";
00232         logger.error(msg);
00233         throw new SQLException(msg);
00234       }
00235 
00236       // Sanity check
00237       if (c == null)
00238       { // Bad connection
00239         SQLException se = new SQLException(
00240             "Unable to retrieve connection for transaction " + tid);
00241         try
00242         { // All backends failed, just ignore
00243           if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, se))
00244             return;
00245         }
00246         catch (SQLException ignore)
00247         {
00248         }
00249         // Disable this backend (it is no more in sync) by killing the
00250         // backend thread
00251         backendThread.kill();
00252         String msg = "Request '"
00253             + proc.getSQLShortForm(backend.getSQLShortFormLength())
00254             + "' failed on backend " + backend.getName() + " but "
00255             + getSuccess() + " succeeded (" + se + ")";
00256         logger.error(msg);
00257         throw new SQLException(msg);
00258       }
00259 
00260       // Execute Query
00261       try
00262       {
00263         result = AbstractLoadBalancer.executeWriteStoredProcedureOnBackend(
00264             proc, backend, c);
00265 
00266         // Warning! No way to detect if schema has been modified unless
00267         // we ask the backend again using DatabaseMetaData.getTables().
00268       }
00269       catch (Exception e)
00270       {
00271         try
00272         { // All backends failed, just ignore
00273           if (!notifyFailure(backendThread, (long) proc.getTimeout() * 1000, e))
00274             return;
00275         }
00276         catch (SQLException ignore)
00277         {
00278         }
00279         // Disable this backend (it is no more in sync) by killing the backend
00280         // thread
00281         backendThread.kill();
00282         String msg = "Stored procedure '"
00283             + proc.getSQLShortForm(backend.getSQLShortFormLength())
00284             + "' failed on backend " + backend.getName() + " but "
00285             + getSuccess() + " succeeded (" + e + ")";
00286         logger.error(msg);
00287         throw new SQLException(msg);
00288       }
00289     }
00290     notifySuccess();
00291   }
00292 
00293   /**
00294    * Returns the result.
00295    * 
00296    * @return int
00297    */
00298   public int getResult()
00299   {
00300     return result;
00301   }
00302 
00303   /**
00304    * @see java.lang.Object#toString()
00305    */
00306   public String toString()
00307   {
00308     if (proc.isAutoCommit())
00309       return "Write autocommit StoredProcedureTask (" + proc.getSQL() + ")";
00310     else
00311       return "Write StoredProcedureTask for transaction:"
00312           + proc.getTransactionId() + "(" + proc.getSQL() + ")";
00313   }
00314 
00315 }

Generated on Mon Apr 11 22:01:35 2005 for C-JDBC by  doxygen 1.3.9.1