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

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

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