1 22 23 package org.continuent.sequoia.controller.loadbalancer.raidb2; 24 25 import java.sql.SQLException ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 29 import org.continuent.sequoia.common.exceptions.NoMoreBackendException; 30 import org.continuent.sequoia.common.exceptions.UnreachableBackendException; 31 import org.continuent.sequoia.common.i18n.Translate; 32 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 33 import org.continuent.sequoia.controller.backend.DatabaseBackend; 34 import org.continuent.sequoia.controller.backend.result.ControllerResultSet; 35 import org.continuent.sequoia.controller.backend.result.ExecuteResult; 36 import org.continuent.sequoia.controller.cache.metadata.MetadataCache; 37 import org.continuent.sequoia.controller.loadbalancer.policies.WaitForCompletionPolicy; 38 import org.continuent.sequoia.controller.loadbalancer.policies.createtable.CreateTablePolicy; 39 import org.continuent.sequoia.controller.requests.SelectRequest; 40 import org.continuent.sequoia.controller.requests.StoredProcedure; 41 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase; 42 43 53 public class RAIDb2_RR extends RAIDb2 54 { 55 59 60 private int index; 62 65 66 76 public RAIDb2_RR(VirtualDatabase vdb, 77 WaitForCompletionPolicy waitForCompletionPolicy, 78 CreateTablePolicy createTablePolicy) throws Exception 79 { 80 super(vdb, waitForCompletionPolicy, createTablePolicy); 81 index = -1; 82 } 83 84 87 88 100 public ControllerResultSet statementExecuteQuery(SelectRequest request, 101 MetadataCache metadataCache) throws SQLException 102 { 103 try 105 { 106 vdb.acquireReadLockBackendLists(); 107 } 108 catch (InterruptedException e) 109 { 110 String msg = Translate.get( 111 "loadbalancer.backendlist.acquire.readlock.failed", e); 112 logger.error(msg); 113 throw new SQLException (msg); 114 } 115 116 DatabaseBackend backend = null; 118 try 121 { 122 ArrayList backends = vdb.getBackends(); 123 int size = backends.size(); 124 125 if (size == 0) 126 throw new NoMoreBackendException(Translate.get( 127 "loadbalancer.execute.no.backend.available", request.getId())); 128 129 int maxTries = size; 131 int enabledBackends = 0; 132 Collection tables = request.getFrom(); 133 if (tables == null) 134 throw new SQLException (Translate.get("loadbalancer.from.not.found", 135 request.getSqlShortForm(vdb.getSqlShortFormLength()))); 136 137 synchronized (this) 138 { 139 do 140 { 141 index = (index + 1) % size; 142 backend = (DatabaseBackend) backends.get(index); 143 if (backend.isReadEnabled()) 144 { 145 enabledBackends++; 146 if (backend.hasTables(tables)) 147 break; 148 } 149 maxTries--; 150 } 151 while (maxTries >= 0); 152 } 153 154 if (maxTries < 0) 155 { if (enabledBackends == 0) 157 throw new NoMoreBackendException(Translate.get( 158 "loadbalancer.execute.no.backend.enabled", request.getId())); 159 else 160 throw new SQLException (Translate.get( 161 "loadbalancer.backend.no.required.tables", tables.toString())); 162 } 163 } 164 catch (RuntimeException e) 165 { 166 String msg = Translate.get("loadbalancer.request.failed.on.backend", 167 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 168 backend.getName(), e.getMessage()}); 169 logger.error(msg, e); 170 throw new SQLException (msg); 171 } 172 finally 173 { 174 vdb.releaseReadLockBackendLists(); 175 } 176 177 ControllerResultSet rs = null; 179 try 180 { 181 rs = executeReadRequestOnBackend(request, backend, metadataCache); 182 } 183 catch (UnreachableBackendException se) 184 { 185 return statementExecuteQuery(request, metadataCache); 187 } 188 catch (SQLException se) 189 { 190 String msg = Translate.get("loadbalancer.request.failed", new String []{ 191 String.valueOf(request.getId()), se.getMessage()}); 192 if (logger.isInfoEnabled()) 193 logger.info(msg); 194 throw new SQLException (msg); 195 } 196 catch (RuntimeException e) 197 { 198 String msg = Translate.get("loadbalancer.request.failed.on.backend", 199 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 200 backend.getName(), e.getMessage()}); 201 logger.error(msg, e); 202 throw new SQLException (msg); 203 } 204 205 return rs; 206 } 207 208 216 public ControllerResultSet readOnlyCallableStatementExecuteQuery( 217 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 218 { 219 return (ControllerResultSet) callStoredProcedure(proc, 220 CALLABLE_STATEMENT_EXECUTE_QUERY, metadataCache); 221 } 222 223 231 public ExecuteResult readOnlyCallableStatementExecute(StoredProcedure proc, 232 MetadataCache metadataCache) throws SQLException 233 { 234 return (ExecuteResult) callStoredProcedure(proc, 235 CALLABLE_STATEMENT_EXECUTE, metadataCache); 236 } 237 238 250 private Object callStoredProcedure(StoredProcedure proc, int callType, 251 MetadataCache metadataCache) throws SQLException 252 { 253 try 255 { 256 vdb.acquireReadLockBackendLists(); 257 } 258 catch (InterruptedException e) 259 { 260 String msg = Translate.get( 261 "loadbalancer.backendlist.acquire.readlock.failed", e); 262 logger.error(msg); 263 throw new SQLException (msg); 264 } 265 266 DatabaseBackend backend = null; 268 try 271 { 272 DatabaseBackend failedBackend = null; 273 SQLException failedException = null; 274 Object result = null; 275 do 276 { 277 ArrayList backends = vdb.getBackends(); 278 int size = backends.size(); 279 280 if (size == 0) 281 throw new NoMoreBackendException(Translate.get( 282 "loadbalancer.execute.no.backend.available", proc.getId())); 283 284 int maxTries = size; 286 int enabledBackends = 0; 287 288 synchronized (this) 289 { 290 do 291 { 292 index = (index + 1) % size; 293 backend = (DatabaseBackend) backends.get(index); 294 if (backend.isReadEnabled()) 295 { 296 enabledBackends++; 297 if ((backend != failedBackend) 298 && backend.hasStoredProcedure(proc.getProcedureKey(), proc 299 .getNbOfParameters())) 300 break; 301 } 302 maxTries--; 303 } 304 while (maxTries >= 0); 305 } 306 307 if (maxTries < 0) 308 { if (enabledBackends == 0) 310 throw new SQLException (Translate.get( 311 "loadbalancer.execute.no.backend.enabled", proc.getId())); 312 else if (failedBackend == null) 313 throw new SQLException (Translate.get( 314 "loadbalancer.backend.no.required.storedprocedure", proc 315 .getProcedureKey())); 316 else 317 throw failedException; 319 } 320 321 boolean toDisable = false; 323 try 324 { 325 switch (callType) 326 { 327 case CALLABLE_STATEMENT_EXECUTE_QUERY : 328 result = executeStoredProcedureOnBackend(proc, true, backend, 329 metadataCache); 330 break; 331 case CALLABLE_STATEMENT_EXECUTE : 332 result = executeStoredProcedureOnBackend(proc, false, backend, 333 metadataCache); 334 break; 335 default : 336 throw new RuntimeException ("Unhandled call type " + callType 337 + " in executeLPRF"); 338 } 339 if (failedBackend != null) 340 { if (logger.isWarnEnabled()) 342 logger.warn(Translate.get("loadbalancer.storedprocedure.status", 343 new String []{String.valueOf(proc.getId()), backend.getName(), 344 failedBackend.getName()})); 345 toDisable = true; 346 } 347 } 348 catch (UnreachableBackendException se) 349 { 350 continue; 352 } 353 catch (SQLException se) 354 { 355 if (failedBackend != null) 356 { String msg = Translate.get( 358 "loadbalancer.storedprocedure.failed.twice", new String []{ 359 String.valueOf(proc.getId()), se.getMessage()}); 360 if (logger.isInfoEnabled()) 361 logger.info(msg); 362 throw new SQLException (msg); 363 } 364 else 365 { failedBackend = backend; 367 failedException = se; 368 if (logger.isInfoEnabled()) 369 logger.info(Translate.get( 370 "loadbalancer.storedprocedure.failed.on.backend", 371 new String []{ 372 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 373 backend.getName(), se.getMessage()})); 374 continue; 375 } 376 } 377 378 if (toDisable) 379 { try 382 { 383 if (logger.isWarnEnabled()) 384 logger.warn(Translate.get("loadbalancer.backend.disabling", 385 failedBackend.getName())); 386 disableBackend(failedBackend, true); 387 } 388 catch (SQLException ignore) 389 { 390 } 391 finally 392 { 393 failedBackend = null; } 395 } 396 } 397 while (failedBackend != null); 398 return result; 399 } 400 catch (Throwable e) 401 { 402 String msg = Translate.get( 403 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 404 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 405 backend.getName(), e.getMessage()}); 406 logger.fatal(msg, e); 407 throw new SQLException (msg); 408 } 409 finally 410 { 411 vdb.releaseReadLockBackendLists(); 412 } 413 } 414 415 418 419 424 public String getInformation() 425 { 426 int size = vdb.getBackends().size(); 428 429 if (size == 0) 430 return "RAIDb-2 Round-Robin Request load balancer: !!!Warning!!! No backend nodes found\n"; 431 else 432 return "RAIDb-2 Round-Robin Request load balancer (" + size 433 + " backends)\n"; 434 } 435 436 439 public String getRaidb2Xml() 440 { 441 return "<" + DatabasesXmlTags.ELT_RAIDb_2_RoundRobin + "/>"; 442 } 443 } | Popular Tags |