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

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

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

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

Collaboration graph
[legend]
List of all members.

Public Member Functions

 RAIDb2_RR (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.

The read requests coming from the request manager are sent in a round robin to the backend nodes. Write requests are broadcasted to all backends.

Author:
Emmanuel Cecchet

Julie Marguerite

Version:
1.0

Definition at line 53 of file RAIDb2_RR.java.


Constructor & Destructor Documentation

org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_RR.RAIDb2_RR 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_RR.java.

00079   {
00080     super(vdb, waitForCompletionPolicy, createTablePolicy);
00081     index = -1;
00082   }


Member Function Documentation

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

Chooses the node to execute the stored procedure using a round-robin 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 213 of file RAIDb2_RR.java.

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

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

ControllerResultSet org.objectweb.cjdbc.controller.loadbalancer.raidb2.RAIDb2_RR.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 100 of file RAIDb2_RR.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.virtualdatabase.VirtualDatabase.getSQLShortFormLength(), org.objectweb.cjdbc.controller.backend.DatabaseBackend.hasTables(), and org.objectweb.cjdbc.controller.backend.DatabaseBackend.isReadEnabled().

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

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

Gets information about the request load balancer.

Returns:
String containing information

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

Definition at line 373 of file RAIDb2_RR.java.

00374   {
00375     // We don't lock since we don't need a completely accurate value
00376     int size = vdb.getBackends().size();
00377 
00378     if (size == 0)
00379       return "RAIDb-2 Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n";
00380     else
00381       return "RAIDb-2 Round-Robin Request load balancer (" + size
00382           + " backends)\n";
00383   }

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

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

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

Definition at line 388 of file RAIDb2_RR.java.

00389   {
00390     return "<" + DatabasesXmlTags.ELT_RAIDb_2_RoundRobin + "/>";
00391   }


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