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

ParallelDB_RR.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.paralleldb;
00026 
00027 import java.sql.SQLException;
00028 import java.util.ArrayList;
00029 
00030 import org.objectweb.cjdbc.common.i18n.Translate;
00031 import org.objectweb.cjdbc.common.sql.AbstractRequest;
00032 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
00033 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00034 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00035 import org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase;
00036 
00037 /**
00038  * This class defines a ParallelDB_RR load balancer. This load balancer performs
00039  * simple round-robin for read and write queries execution.
00040  * 
00041  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00042  * @version 1.0
00043  */
00044 public class ParallelDB_RR extends ParallelDB
00045 {
00046 
00047   private int index = 0;
00048 
00049   /**
00050    * Creates a new <code>ParallelDB_RR</code> object
00051    * 
00052    * @param vdb the virtual database this load balancer belongs to.
00053    * @throws Exception if an error occurs
00054    */
00055   public ParallelDB_RR(VirtualDatabase vdb) throws Exception
00056   {
00057     super(vdb);
00058   }
00059 
00060   /**
00061    * Choose a backend using a round-robin algorithm for read request execution.
00062    * 
00063    * @param request request to execute
00064    * @return the chosen backend
00065    * @throws SQLException if an error occurs
00066    */
00067   public DatabaseBackend chooseBackendForReadRequest(AbstractRequest request)
00068       throws SQLException
00069   {
00070     // Choose a backend
00071     try
00072     {
00073       vdb.acquireReadLockBackendLists();
00074     }
00075     catch (InterruptedException e)
00076     {
00077       String msg = Translate.get(
00078           "loadbalancer.backendlist.acquire.readlock.failed", e);
00079       logger.error(msg);
00080       throw new SQLException(msg);
00081     }
00082 
00083     DatabaseBackend backend = null; // The backend that will execute the query
00084 
00085     // Note that vdb lock is released in the finally clause of this try/catch
00086     // block
00087     try
00088     {
00089       ArrayList backends = vdb.getBackends();
00090       int size = backends.size();
00091 
00092       if (size == 0)
00093         throw new SQLException(Translate.get(
00094             "loadbalancer.execute.no.backend.available", request.getId()));
00095 
00096       // Take the next backend
00097       int maxTries = size;
00098       synchronized (this)
00099       {
00100         do
00101         {
00102           index = (index + 1) % size;
00103           backend = (DatabaseBackend) backends.get(index);
00104           maxTries--;
00105         }
00106         while ((!backend.isReadEnabled() && maxTries >= 0));
00107       }
00108 
00109       if (maxTries < 0)
00110         throw new SQLException(Translate.get(
00111             "loadbalancer.execute.no.backend.enabled", request.getId()));
00112     }
00113     catch (RuntimeException e)
00114     {
00115       String msg = Translate.get("loadbalancer.execute.find.backend.failed",
00116           new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00117               e.getMessage()});
00118       logger.error(msg, e);
00119       throw new SQLException(msg);
00120     }
00121     finally
00122     {
00123       vdb.releaseReadLockBackendLists();
00124     }
00125     return backend;
00126   }
00127 
00128   /**
00129    * Choose a backend using a round-robin algorithm for write request execution.
00130    * 
00131    * @param request request to execute
00132    * @return the chosen backend
00133    * @throws SQLException if an error occurs
00134    */
00135   public DatabaseBackend chooseBackendForWriteRequest(
00136       AbstractWriteRequest request) throws SQLException
00137   {
00138     // Choose a backend
00139     try
00140     {
00141       vdb.acquireReadLockBackendLists();
00142     }
00143     catch (InterruptedException e)
00144     {
00145       String msg = Translate.get(
00146           "loadbalancer.backendlist.acquire.readlock.failed", e);
00147       logger.error(msg);
00148       throw new SQLException(msg);
00149     }
00150 
00151     DatabaseBackend backend = null; // The backend that will execute the query
00152 
00153     // Note that vdb lock is released in the finally clause of this try/catch
00154     // block
00155     try
00156     {
00157       ArrayList backends = vdb.getBackends();
00158       int size = backends.size();
00159 
00160       if (size == 0)
00161         throw new SQLException(Translate.get(
00162             "loadbalancer.execute.no.backend.available", request.getId()));
00163 
00164       // Take the next backend
00165       int maxTries = size;
00166       synchronized (this)
00167       {
00168         do
00169         {
00170           index = (index + 1) % size;
00171           backend = (DatabaseBackend) backends.get(index);
00172           maxTries--;
00173         }
00174         while ((!backend.isWriteEnabled() || backend.isDisabling())
00175             && (maxTries >= 0));
00176       }
00177 
00178       if (maxTries < 0)
00179         throw new SQLException(Translate.get(
00180             "loadbalancer.execute.no.backend.enabled", request.getId()));
00181     }
00182     catch (RuntimeException e)
00183     {
00184       String msg = Translate.get("loadbalancer.execute.find.backend.failed",
00185           new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00186               e.getMessage()});
00187       logger.error(msg, e);
00188       throw new SQLException(msg);
00189     }
00190     finally
00191     {
00192       vdb.releaseReadLockBackendLists();
00193     }
00194     return backend;
00195   }
00196 
00197   /**
00198    * @see org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer#getInformation()
00199    */
00200   public String getInformation()
00201   {
00202     // We don't lock since we don't need a top accurate value
00203     int size = vdb.getBackends().size();
00204 
00205     if (size == 0)
00206       return "ParallelDB Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n";
00207     else
00208       return "ParallelDB Round-Robin Request load balancer (" + size
00209           + " backends)\n";
00210   }
00211 
00212   /**
00213    * @see org.objectweb.cjdbc.controller.loadbalancer.paralleldb.ParallelDB#getParallelDBXml()
00214    */
00215   public String getParallelDBXml()
00216   {
00217     return "<" + DatabasesXmlTags.ELT_ParallelDB_RoundRobin + "/>";
00218   }
00219 }

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