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 () |
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.
Definition at line 53 of file RAIDb2_RR.java.
|
Creates a new RAIDb-2 Round Robin request load balancer.
Definition at line 76 of file RAIDb2_RR.java. 00079 { 00080 super(vdb, waitForCompletionPolicy, createTablePolicy); 00081 index = -1; 00082 }
|
|
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.
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 }
|
|
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.
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 }
|
|
Gets information about the request load balancer.
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 }
|
|
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 }
|