src/org/objectweb/cjdbc/controller/loadbalancer/raidb2/RAIDb2_RR.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 00053 public class RAIDb2_RR extends RAIDb2 00054 { 00055 /* 00056 * How the code is organized ? 1. Member variables 2. Constructor(s) 3. 00057 * Request handling 4. Debug/Monitoring 00058 */ 00059 00060 private int index; // index in the backend vector the Round-Robin 00061 00062 /* 00063 * Constructors 00064 */ 00065 00076 public RAIDb2_RR(VirtualDatabase vdb, 00077 WaitForCompletionPolicy waitForCompletionPolicy, 00078 CreateTablePolicy createTablePolicy) throws SQLException 00079 { 00080 super(vdb, waitForCompletionPolicy, createTablePolicy); 00081 index = -1; 00082 } 00083 00084 /* 00085 * Request Handling 00086 */ 00087 00100 public ControllerResultSet execReadRequest(SelectRequest request, 00101 MetadataCache metadataCache) throws SQLException 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 } 00204 00213 public ControllerResultSet execReadOnlyReadStoredProcedure( 00214 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 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 failedBackend.disable(); 00336 failedBackend.finalizeConnections(); 00337 } 00338 catch (SQLException ignore) 00339 { 00340 } 00341 finally 00342 { 00343 failedBackend = null; // to exit the do{}while 00344 } 00345 } 00346 } 00347 while (failedBackend != null); 00348 return rs; 00349 } 00350 catch (RuntimeException e) 00351 { 00352 String msg = Translate.get( 00353 "loadbalancer.storedprocedure.failed.on.backend", new String[]{ 00354 proc.getSQLShortForm(vdb.getSQLShortFormLength()), 00355 backend.getName(), e.getMessage()}); 00356 logger.fatal(msg, e); 00357 throw new SQLException(msg); 00358 } 00359 finally 00360 { 00361 vdb.releaseReadLockBackendLists(); 00362 } 00363 } 00364 00365 /* 00366 * Debug/Monitoring 00367 */ 00368 00374 public String getInformation() 00375 { 00376 // We don't lock since we don't need a completely accurate value 00377 int size = vdb.getBackends().size(); 00378 00379 if (size == 0) 00380 return "RAIDb-2 Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n"; 00381 else 00382 return "RAIDb-2 Round-Robin Request load balancer (" + size 00383 + " backends)\n"; 00384 } 00385 00389 public String getRaidb2Xml() 00390 { 00391 return "<" + DatabasesXmlTags.ELT_RAIDb_2_RoundRobin + "/>"; 00392 } 00393 }

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