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

org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF Class Reference

Inheritance diagram for org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF:

Inheritance graph
[legend]
Collaboration diagram for org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 RAIDb2_LPRF (VirtualDatabase vdb, WaitForCompletionPolicy waitForCompletionPolicy, CreateTablePolicy createTablePolicy) throws Exception
ControllerResultSet execReadRequest (SelectRequest request, MetadataCache metadataCache) throws SQLException
ControllerResultSet execReadOnlyReadStoredProcedure (StoredProcedure proc, MetadataCache metadataCache) throws SQLException
String getInformation ()
String getRaidb2Xml ()

Detailed Description

RAIDb-2 Round Robin load balancer featuring (Least Pending Requests First load balancing algorithm).

The read requests coming from the request manager are sent to the node that has the Least pending read requests among the nodes that can execute the request.

Author:
Emmanuel Cecchet
Version:
1.0

Definition at line 54 of file RAIDb2_LPRF.java.


Constructor & Destructor Documentation

org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF.RAIDb2_LPRF VirtualDatabase  vdb,
WaitForCompletionPolicy  waitForCompletionPolicy,
CreateTablePolicy  createTablePolicy
throws Exception
 

Creates a new RAIDb-2 Round Robin request load balancer.

Parameters:
vdb the virtual database this load balancer belongs to.
waitForCompletionPolicy how many backends must complete before returning the result?
createTablePolicy the policy defining how 'create table' statements should be handled
Exceptions:
Exception if an error occurs

Definition at line 76 of file RAIDb2_LPRF.java.

00079   {
00080     super(vdb, waitForCompletionPolicy, createTablePolicy);
00081   }


Member Function Documentation

ControllerResultSet org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF.execReadOnlyReadStoredProcedure StoredProcedure  proc,
MetadataCache  metadataCache
throws SQLException [virtual]
 

Chooses the node to execute the stored procedure using a LPRF algorithm. If the next node has not the needed stored procedure, we try the next one and so on until a suitable backend is found.

See also:
org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer.execReadOnlyReadStoredProcedure(StoredProcedure, MetadataCache)

Implements org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer.

Definition at line 217 of file RAIDb2_LPRF.java.

References org.objectweb.cjdbc.controller.backend.DatabaseBackend.getName(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.getPendingRequests(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.hasStoredProcedure(), and org.objectweb.cjdbc.controller.backend.DatabaseBackend.isReadEnabled().

00219   {
00220     // Choose a backend
00221     try
00222     {
00223       vdb.acquireReadLockBackendLists();
00224     }
00225     catch (InterruptedException e)
00226     {
00227       String msg = Translate.get(
00228           "loadbalancer.backendlist.acquire.readlock.failed", e);
00229       logger.error(msg);
00230       throw new SQLException(msg);
00231     }
00232 
00233     DatabaseBackend backend = null; // The backend that will execute the query
00234 
00235     // Note that vdb lock is released in the finally clause of this try/catch
00236     // block
00237     try
00238     {
00239       DatabaseBackend failedBackend = null;
00240       SQLException failedException = null;
00241       ControllerResultSet rs = null;
00242       do
00243       {
00244         ArrayList backends = vdb.getBackends();
00245         int size = backends.size();
00246 
00247         if (size == 0)
00248           throw new SQLException(Translate.get(
00249               "loadbalancer.execute.no.backend.available", proc.getId()));
00250 
00251         // Choose the backend that has the least pending requests
00252         int leastRequests = 0;
00253         int enabledBackends = 0;
00254 
00255         for (int i = 0; i < size; i++)
00256         {
00257           DatabaseBackend b = (DatabaseBackend) backends.get(i);
00258           if (b.isReadEnabled())
00259           {
00260             enabledBackends++;
00261             if (b.hasStoredProcedure(proc.getProcedureName()))
00262             {
00263               int pending = b.getPendingRequests().size();
00264               if ((b != failedBackend)
00265                   && ((backend == null) || (pending < leastRequests)))
00266               {
00267                 backend = b;
00268                 if (pending == 0)
00269                   break; // Stop here we will never find a less loaded node
00270                 else
00271                   leastRequests = pending;
00272               }
00273             }
00274           }
00275         }
00276 
00277         if (backend == null)
00278         {
00279           if (enabledBackends == 0)
00280             throw new SQLException(Translate
00281                 .get("loadbalancer.storedprocedure.backend.no.enabled", proc
00282                     .getId()));
00283           else if (failedBackend == null)
00284             throw new SQLException(Translate.get(
00285                 "loadbalancer.backend.no.required.storedprocedure", proc
00286                     .getProcedureName()));
00287           else
00288             // Bad query, the only backend that could execute it has failed
00289             throw failedException;
00290         }
00291 
00292         // Execute the request on the chosen backend
00293         boolean toDisable = false;
00294         try
00295         {
00296           rs = executeStoredProcedureOnBackend(proc, backend, metadataCache);
00297           if (failedBackend != null)
00298           { // Previous backend failed
00299             if (logger.isWarnEnabled())
00300               logger.warn(Translate.get("loadbalancer.storedprocedure.status",
00301                   new String[]{String.valueOf(proc.getId()), backend.getName(),
00302                       failedBackend.getName()}));
00303             toDisable = true;
00304           }
00305         }
00306         catch (UnreachableBackendException se)
00307         {
00308           // Retry on an other backend.
00309           continue;
00310         }
00311         catch (SQLException se)
00312         {
00313           if (failedBackend != null)
00314           { // Bad query, no backend can execute it
00315             String msg = Translate.get(
00316                 "loadbalancer.storedprocedure.failed.twice", new String[]{
00317                     String.valueOf(proc.getId()), se.getMessage()});
00318             if (logger.isInfoEnabled())
00319               logger.info(msg);
00320             throw new SQLException(msg);
00321           }
00322           else
00323           { // We are the first to fail on this query
00324             failedBackend = backend;
00325             failedException = se;
00326             if (logger.isInfoEnabled())
00327               logger.info(Translate.get(
00328                   "loadbalancer.storedprocedure.failed.on.backend",
00329                   new String[]{
00330                       proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00331                       backend.getName(), se.getMessage()}));
00332             continue;
00333           }
00334         }
00335 
00336         if (toDisable)
00337         { // retry has succeeded and we need to disable the first node that
00338           // failed
00339           try
00340           {
00341             if (logger.isWarnEnabled())
00342               logger.warn(Translate.get("loadbalancer.backend.disabling",
00343                   failedBackend.getName()));
00344             disableBackend(failedBackend);
00345           }
00346           catch (SQLException ignore)
00347           {
00348           }
00349           finally
00350           {
00351             failedBackend = null; // to exit the do{}while
00352           }
00353         }
00354       }
00355       while (failedBackend != null);
00356       return rs;
00357     }
00358     catch (RuntimeException e)
00359     {
00360       String msg = Translate.get(
00361           "loadbalancer.storedprocedure.failed.on.backend", new String[]{
00362               proc.getSQLShortForm(vdb.getSQLShortFormLength()),
00363               backend.getName(), e.getMessage()});
00364       logger.fatal(msg, e);
00365       throw new SQLException(msg);
00366     }
00367     finally
00368     {
00369       vdb.releaseReadLockBackendLists();
00370     }
00371   }

ControllerResultSet org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF.execReadRequest SelectRequest  request,
MetadataCache  metadataCache
throws SQLException [virtual]
 

Chooses the node to execute the request using a round-robin algorithm. If the next node has not the tables needed to execute the requests, we try the next one and so on until a suitable backend is found.

Parameters:
request an SelectRequest
metadataCache cached metadata to use to construct the result set
Returns:
the corresponding java.sql.ResultSet
Exceptions:
SQLException if an error occurs
See also:
org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2.execReadRequest(SelectRequest, MetadataCache)

Implements org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2.

Definition at line 99 of file RAIDb2_LPRF.java.

References org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase.acquireReadLockBackendLists(), org.objectweb.cjdbc.common.log.Trace.error(), org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase.getBackends(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.getName(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.getPendingRequests(), org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase.getSQLShortFormLength(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.hasTables(), and org.objectweb.cjdbc.controller.backend.DatabaseBackend.isReadEnabled().

00101   {
00102     // Choose a backend
00103     try
00104     {
00105       vdb.acquireReadLockBackendLists();
00106     }
00107     catch (InterruptedException e)
00108     {
00109       String msg = Translate.get(
00110           "loadbalancer.backendlist.acquire.readlock.failed", e);
00111       logger.error(msg);
00112       throw new SQLException(msg);
00113     }
00114 
00115     DatabaseBackend backend = null; // The backend that will execute the query
00116 
00117     // Note that vdb lock is released in the finally clause of this try/catch
00118     // block
00119     try
00120     {
00121       ArrayList backends = vdb.getBackends();
00122       int size = backends.size();
00123 
00124       if (size == 0)
00125         throw new SQLException(Translate.get(
00126             "loadbalancer.execute.no.backend.available", request.getId()));
00127 
00128       // Choose the backend that has the least pending requests
00129       int leastRequests = 0;
00130       int enabledBackends = 0;
00131       ArrayList tables = request.getFrom();
00132 
00133       for (int i = 0; i < size; i++)
00134       {
00135         DatabaseBackend b = (DatabaseBackend) backends.get(i);
00136         if (b.isReadEnabled())
00137         {
00138           enabledBackends++;
00139           if (b.hasTables(tables))
00140           {
00141             int pending = b.getPendingRequests().size();
00142             if (((backend == null) || (pending < leastRequests)))
00143             {
00144               backend = b;
00145               if (pending == 0)
00146                 break; // Stop here we will never find a less loaded node
00147               else
00148                 leastRequests = pending;
00149             }
00150           }
00151         }
00152       }
00153 
00154       if (backend == null)
00155       {
00156         if (enabledBackends == 0)
00157           throw new NoMoreBackendException(Translate.get(
00158               "loadbalancer.execute.no.backend.enabled", request.getId()));
00159         else
00160           throw new SQLException(Translate.get(
00161               "loadbalancer.backend.no.required.tables", tables.toString()));
00162       }
00163 
00164     }
00165     catch (RuntimeException e)
00166     {
00167       String msg = Translate.get("loadbalancer.request.failed.on.backend",
00168           new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00169               backend.getName(), e.getMessage()});
00170       logger.error(msg, e);
00171       throw new SQLException(msg);
00172     }
00173     finally
00174     {
00175       vdb.releaseReadLockBackendLists();
00176     }
00177 
00178     // Execute the request on the chosen backend
00179     ControllerResultSet rs = null;
00180     try
00181     {
00182       rs = executeRequestOnBackend(request, backend, metadataCache);
00183     }
00184     catch (UnreachableBackendException se)
00185     {
00186       // Try on another backend
00187       return execReadRequest(request, metadataCache);
00188     }
00189     catch (SQLException se)
00190     {
00191       String msg = Translate.get("loadbalancer.request.failed", new String[]{
00192           String.valueOf(request.getId()), se.getMessage()});
00193       if (logger.isInfoEnabled())
00194         logger.info(msg);
00195       throw new SQLException(msg);
00196     }
00197     catch (RuntimeException e)
00198     {
00199       String msg = Translate.get("loadbalancer.request.failed.on.backend",
00200           new String[]{request.getSQLShortForm(vdb.getSQLShortFormLength()),
00201               backend.getName(), e.getMessage()});
00202       logger.error(msg, e);
00203       throw new SQLException(msg);
00204     }
00205 
00206     return rs;
00207   }

String org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF.getInformation  )  [virtual]
 

Gets information about the request load balancer.

Returns:
String containing information

Implements org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer.

Definition at line 382 of file RAIDb2_LPRF.java.

00383   {
00384     // We don't lock since we don't need a completely accurate value
00385     int size = vdb.getBackends().size();
00386 
00387     if (size == 0)
00388       return "RAIDb-2 Least Pending Requests First load balancer: !!!Warning!!! No backend nodes found\n";
00389     else
00390       return "RAIDb-2 Least Pending Requests First load balancer (" + size
00391           + " backends)\n";
00392   }

String org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_LPRF.getRaidb2Xml  )  [virtual]
 

See also:
org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2.getRaidb2Xml

Implements org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2.

Definition at line 397 of file RAIDb2_LPRF.java.

00398   {
00399     return "<" + DatabasesXmlTags.ELT_RAIDb_2_LeastPendingRequestsFirst + "/>";
00400   }


The documentation for this class was generated from the following file:
Generated on Mon Apr 11 22:04:09 2005 for C-JDBC by  doxygen 1.3.9.1