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

BeginTask.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.
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.controller.backend.DatabaseBackend;
00034 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager;
00035 import org.objectweb.cjdbc.controller.loadbalancer.BackendWorkerThread;
00036 
00037 /**
00038  * Task to begin a transaction.
00039  * 
00040  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00041  * @author <a href="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
00042  * @version 1.0
00043  */
00044 public class BeginTask extends AbstractTask
00045 {
00046   /** Login used by the connection. */
00047   private String login;
00048 
00049   /** Unique transaction identifier. */
00050   private long   transactionId;
00051 
00052   /** Request timeout in milliseconds. */
00053   private long   timeout;
00054 
00055   /**
00056    * Begins a new transaction given a login and a transaction id.
00057    * 
00058    * @param nbToComplete number of threads that must succeed before returning
00059    * @param totalNb total number of threads
00060    * @param timeout request timeout in milliseconds
00061    * @param login the login used by the connection
00062    * @param transactionId a unique transaction identifier
00063    */
00064   public BeginTask(int nbToComplete, int totalNb, long timeout, String login,
00065       long transactionId)
00066   {
00067     super(nbToComplete, totalNb);
00068     this.login = login;
00069     this.transactionId = transactionId;
00070     this.timeout = timeout;
00071   }
00072 
00073   /**
00074    * Begins a new transaction with the given backend thread.
00075    * 
00076    * @param backendThread the backend thread that will execute the task
00077    * @exception SQLException if an error occurs
00078    */
00079   public void executeTask(BackendWorkerThread backendThread)
00080       throws SQLException
00081   {
00082     DatabaseBackend backend = backendThread.getBackend();
00083     if (backend.isDisabling())
00084     {
00085       // Backend is disabling, we do not execute queries except the one in the
00086       // transaction we already started. Just notify the completion for the
00087       // others.
00088       notifyCompletion();
00089       return;
00090     }
00091 
00092     try
00093     {
00094       AbstractConnectionManager cm = backend.getConnectionManager(login);
00095       if (cm == null)
00096       {
00097         SQLException se = new SQLException(
00098             "No Connection Manager for Virtual Login:" + login);
00099         try
00100         {
00101           notifyFailure(backendThread, 1, se);
00102         }
00103         catch (SQLException ignore)
00104         {
00105 
00106         }
00107         throw se;
00108       }
00109 
00110       Connection c;
00111       Long lTid = new Long(transactionId);
00112       Trace logger = backendThread.getLogger();
00113 
00114       try
00115       {
00116         c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(lTid, cm);
00117       }
00118       catch (UnreachableBackendException ube)
00119       {
00120         SQLException se = new SQLException("Backend " + backend.getName()
00121             + " is no more reachable.");
00122         try
00123         {
00124           notifyFailure(backendThread, 1, se);
00125         }
00126         catch (SQLException ignore)
00127         {
00128         }
00129         // Disable this backend (it is no more in sync) by killing the backend
00130         // thread
00131         backendThread.kill();
00132         logger.error("Disabling backend " + backend.getName()
00133             + " because it is no more reachable.");
00134         throw se;
00135       }
00136       catch (NoTransactionStartWhenDisablingException e)
00137       {
00138         // Backend is disabling, we do not execute queries except the one in the
00139         // transaction we already started. Just notify the completion for the
00140         // others.
00141         notifyCompletion();
00142         return;
00143       }
00144       catch (SQLException e1)
00145       {
00146         SQLException se = new SQLException(
00147             "Unable to get connection for transaction " + lTid);
00148         try
00149         { // All backends failed, just ignore
00150           if (!notifyFailure(backendThread, timeout * 1000, se))
00151             return;
00152         }
00153         catch (SQLException ignore)
00154         {
00155         }
00156         // Disable this backend (it is no more in sync) by killing the
00157         // backend thread
00158         backendThread.kill();
00159         String msg = "Begin of transaction " + transactionId
00160             + " failed on backend " + backend.getName() + " but "
00161             + getSuccess() + " succeeded (" + se + ")";
00162         logger.error(msg);
00163         throw new SQLException(msg);
00164       }
00165 
00166       // Sanity check
00167       if (c == null)
00168       { // Bad connection
00169         SQLException se = new SQLException(
00170             "No more connection to start a new transaction.");
00171         try
00172         { // All backends failed, just ignore
00173           if (!notifyFailure(backendThread, timeout, se))
00174             return;
00175         }
00176         catch (SQLException ignore)
00177         {
00178         }
00179       }
00180       else
00181       {
00182         notifyCompletion();
00183       }
00184     }
00185     catch (Exception e)
00186     {
00187       try
00188       {
00189         if (!notifyFailure(backendThread, timeout, new SQLException(e
00190             .getMessage())))
00191           return;
00192       }
00193       catch (SQLException ignore)
00194       {
00195       }
00196       String msg = "Failed to begin transaction " + transactionId
00197           + " on backend " + backend.getName() + " (" + e + ")";
00198       backendThread.getLogger().error(msg);
00199       throw new SQLException(msg);
00200     }
00201   }
00202 
00203   /**
00204    * @see java.lang.Object#toString()
00205    */
00206   public String toString()
00207   {
00208     return "BeginTask (" + transactionId + ")";
00209   }
00210 }

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