src/org/objectweb/cjdbc/controller/loadbalancer/raidb2/RAIDb2_LPRF.java

説明を見る。
00001 00025 package org.objectweb.cjdbc.controller.loadbalancer.raidb2; 00026 00027 import java.sql.SQLException; 00028 import java.util.ArrayList; 00029 00030 import org.objectweb.cjdbc.common.exceptions.NoMoreBackendException; 00031 import org.objectweb.cjdbc.common.exceptions.UnreachableBackendException; 00032 import org.objectweb.cjdbc.common.i18n.Translate; 00033 import org.objectweb.cjdbc.common.sql.SelectRequest; 00034 import org.objectweb.cjdbc.common.sql.StoredProcedure; 00035 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags; 00036 import org.objectweb.cjdbc.controller.backend.DatabaseBackend; 00037 import org.objectweb.cjdbc.controller.cache.metadata.MetadataCache; 00038 import org.objectweb.cjdbc.controller.loadbalancer.policies.WaitForCompletionPolicy; 00039 import org.objectweb.cjdbc.controller.loadbalancer.policies.createtable.CreateTablePolicy; 00040 import org.objectweb.cjdbc.controller.virtualdatabase.ControllerResultSet; 00041 import org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase; 00042 00054 public class RAIDb2_LPRF extends RAIDb2 00055 { 00056 00057 /* 00058 * How the code is organized ? 1. Member variables 2. Constructor(s) 3. 00059 * Request handling 4. Debug/Monitoring 00060 */ 00061 00062 /* 00063 * Constructors 00064 */ 00065 00076 public RAIDb2_LPRF(VirtualDatabase vdb, 00077 WaitForCompletionPolicy waitForCompletionPolicy, 00078 CreateTablePolicy createTablePolicy) throws SQLException 00079 { 00080 super(vdb, waitForCompletionPolicy, createTablePolicy); 00081 } 00082 00083 /* 00084 * Request Handling 00085 */ 00086 00099 public ControllerResultSet execReadRequest(SelectRequest request, 00100 MetadataCache metadataCache) throws SQLException 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 } 00208 00217 public ControllerResultSet execReadOnlyReadStoredProcedure( 00218 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 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 failedBackend.disable(); 00345 failedBackend.finalizeConnections(); 00346 } 00347 catch (SQLException ignore) 00348 { 00349 } 00350 finally 00351 { 00352 failedBackend = null; // to exit the do{}while 00353 } 00354 } 00355 } 00356 while (failedBackend != null); 00357 return rs; 00358 } 00359 catch (RuntimeException e) 00360 { 00361 String msg = Translate.get( 00362 "loadbalancer.storedprocedure.failed.on.backend", new String[]{ 00363 proc.getSQLShortForm(vdb.getSQLShortFormLength()), 00364 backend.getName(), e.getMessage()}); 00365 logger.fatal(msg, e); 00366 throw new SQLException(msg); 00367 } 00368 finally 00369 { 00370 vdb.releaseReadLockBackendLists(); 00371 } 00372 } 00373 00374 /* 00375 * Debug/Monitoring 00376 */ 00377 00383 public String getInformation() 00384 { 00385 // We don't lock since we don't need a completely accurate value 00386 int size = vdb.getBackends().size(); 00387 00388 if (size == 0) 00389 return "RAIDb-2 Least Pending Requests First load balancer: !!!Warning!!! No backend nodes found\n"; 00390 else 00391 return "RAIDb-2 Least Pending Requests First load balancer (" + size 00392 + " backends)\n"; 00393 } 00394 00398 public String getRaidb2Xml() 00399 { 00400 return "<" + DatabasesXmlTags.ELT_RAIDb_2_LeastPendingRequestsFirst + "/>"; 00401 } 00402 }

CJDBCversion1.0.4に対してTue Oct 12 15:16:02 2004に生成されました。 doxygen 1.3.8