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

SelectRequestTask.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): Julie Marguerite, Jaco Swart.
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.NoTransactionStartWhenDisablingException;
00031 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException;
00032 import org.objectweb.cjdbc.common.log.Trace;
00033 import org.objectweb.cjdbc.common.sql.SelectRequest;
00034 import org.objectweb.cjdbc.common.util.Constants;
00035 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00036 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager;
00037 import org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer;
00038 import org.objectweb.cjdbc.controller.loadbalancer.BackendWorkerThread;
00039 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet;
00040 
00041 /**
00042  * Executes a <code>SELECT</code> statement.
00043  * 
00044  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00045  * @author <a href="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
00046  * @author <a href="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
00047  * @version 1.0
00048  */
00049 public class SelectRequestTask extends AbstractTask
00050 {
00051   private SelectRequest       request;
00052   private ControllerResultSet result;
00053 
00054   /**
00055    * Creates a new <code>WriteRequestTask</code> instance.
00056    * 
00057    * @param nbToComplete number of threads that must succeed before returning
00058    * @param totalNb total number of threads
00059    * @param request an <code>AbstractWriteRequest</code>
00060    */
00061   public SelectRequestTask(int nbToComplete, int totalNb, SelectRequest request)
00062   {
00063     super(nbToComplete, totalNb);
00064     this.request = request;
00065   }
00066 
00067   /**
00068    * Executes a write request with the given backend thread
00069    * 
00070    * @param backendThread the backend thread that will execute the task
00071    * @throws SQLException if an error occurs
00072    */
00073   public void executeTask(BackendWorkerThread backendThread)
00074       throws SQLException
00075   {
00076     DatabaseBackend backend = backendThread.getBackend();
00077 
00078     AbstractConnectionManager cm = backend.getConnectionManager(request
00079         .getLogin());
00080     if (cm == null)
00081     {
00082       SQLException se = new SQLException(
00083           "No Connection Manager for Virtual Login:" + request.getLogin());
00084       try
00085       {
00086         notifyFailure(backendThread, 1, se);
00087       }
00088       catch (SQLException ignore)
00089       {
00090 
00091       }
00092       throw se;
00093     }
00094 
00095     Trace logger = backendThread.getLogger();
00096     if (request.isAutoCommit())
00097     { // Use a connection just for this request
00098       Connection c = null;
00099       try
00100       {
00101         c = cm.getConnection();
00102       }
00103       catch (UnreachableBackendException e1)
00104       {
00105         SQLException se = new SQLException("Backend " + backend.getName()
00106             + " is no more reachable.");
00107         try
00108         {
00109           notifyFailure(backendThread, 1, se);
00110         }
00111         catch (SQLException ignore)
00112         {
00113         }
00114         // Disable this backend (it is no more in sync) by killing the backend
00115         // thread
00116         backendThread.kill();
00117         logger.error("Disabling backend " + backend.getName()
00118             + " because it is no more reachable.");
00119         throw se;
00120       }
00121 
00122       // Sanity check
00123       if (c == null)
00124       {
00125         SQLException se = new SQLException("No more connections");
00126         try
00127         { // All backends failed, just ignore
00128           if (!notifyFailure(backendThread, (long) request.getTimeout() * 1000,
00129               se))
00130             return;
00131         }
00132         catch (SQLException ignore)
00133         {
00134         }
00135         // Disable this backend (it is no more in sync) by killing the backend
00136         // thread
00137         backendThread.kill();
00138         throw new SQLException("Request '"
00139             + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
00140             + "' failed on backend " + backend.getName() + " (" + se + ")");
00141       }
00142 
00143       // Execute Query
00144       try
00145       {
00146         result = AbstractLoadBalancer.executeSelectRequestOnBackend(request,
00147             backend, c, null);
00148       }
00149       catch (Exception e)
00150       {
00151         try
00152         { // All backends failed, just ignore
00153           if (!notifyFailure(backendThread, (long) request.getTimeout() * 1000,
00154               e))
00155             return;
00156         }
00157         catch (SQLException ignore)
00158         {
00159         }
00160         throw new SQLException("Request '"
00161             + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
00162             + "' failed on backend " + backend.getName() + " (" + e + ")");
00163       }
00164       finally
00165       {
00166         cm.releaseConnection(c);
00167       }
00168     }
00169     else
00170     {
00171       Connection c;
00172       long tid = request.getTransactionId();
00173       Long lTid = new Long(tid);
00174 
00175       try
00176       {
00177         c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(lTid, cm);
00178       }
00179       catch (UnreachableBackendException ube)
00180       {
00181         SQLException se = new SQLException("Backend " + backend.getName()
00182             + " is no more reachable.");
00183         try
00184         {
00185           notifyFailure(backendThread, 1, se);
00186         }
00187         catch (SQLException ignore)
00188         {
00189         }
00190         // Disable this backend (it is no more in sync) by killing the backend
00191         // thread
00192         backendThread.kill();
00193         logger.error("Disabling backend " + backend.getName()
00194             + " because it is no more reachable.");
00195         throw se;
00196       }
00197       catch (NoTransactionStartWhenDisablingException e)
00198       {
00199         logger
00200             .error("Disabling backend "
00201                 + backend.getName()
00202                 + " has been assigned a select request but it cannot start a new transaction for it.");
00203         notifyFailure(backendThread, (long) request.getTimeout() * 1000, e);
00204         return;
00205       }
00206       catch (SQLException e1)
00207       {
00208         SQLException se = new SQLException(
00209             "Unable to get connection for transaction " + tid);
00210         try
00211         { // All backends failed, just ignore
00212           if (!notifyFailure(backendThread, (long) request.getTimeout() * 1000,
00213               se))
00214             return;
00215         }
00216         catch (SQLException ignore)
00217         {
00218         }
00219         // Disable this backend (it is no more in sync) by killing the
00220         // backend thread
00221         backendThread.kill();
00222         String msg = "Request '"
00223             + request.getSQLShortForm(backend.getSQLShortFormLength())
00224             + "' failed on backend " + backend.getName() + " but "
00225             + getSuccess() + " succeeded (" + se + ")";
00226         logger.error(msg);
00227         throw new SQLException(msg);
00228       }
00229 
00230       // Sanity check
00231       if (c == null)
00232       { // Bad connection
00233         SQLException se = new SQLException(
00234             "Unable to retrieve connection for transaction " + tid);
00235         try
00236         { // All backends failed, just ignore
00237           if (!notifyFailure(backendThread, (long) request.getTimeout() * 1000,
00238               se))
00239             return;
00240         }
00241         catch (SQLException ignore)
00242         {
00243         }
00244         // Disable this backend (it is no more in sync) by killing the
00245         // backend thread
00246         backendThread.kill();
00247         String msg = "Request '"
00248             + request.getSQLShortForm(backend.getSQLShortFormLength())
00249             + "' failed on backend " + backend.getName() + " but "
00250             + getSuccess() + " succeeded (" + se + ")";
00251         logger.error(msg);
00252         throw new SQLException(msg);
00253       }
00254 
00255       // Execute Query
00256       try
00257       {
00258         result = AbstractLoadBalancer.executeSelectRequestOnBackend(request,
00259             backend, c, null);
00260       }
00261       catch (Exception e)
00262       {
00263         try
00264         { // All backends failed, just ignore
00265           if (!notifyFailure(backendThread, (long) request.getTimeout() * 1000,
00266               e))
00267             return;
00268         }
00269         catch (SQLException ignore)
00270         {
00271         }
00272         throw new SQLException("Request '"
00273             + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
00274             + "' failed on backend " + backend.getName() + " (" + e + ")");
00275       }
00276     }
00277     notifySuccess();
00278   }
00279 
00280   /**
00281    * Returns the result.
00282    * 
00283    * @return a <code>ResultSet</code>
00284    */
00285   public ControllerResultSet getResult()
00286   {
00287     return result;
00288   }
00289 
00290   /**
00291    * @see java.lang.Object#toString()
00292    */
00293   public String toString()
00294   {
00295     return "SelectRequestTask (" + request.getSQL() + ")";
00296   }
00297 }

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