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