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 54 public class RAIDb2_LPRF extends RAIDb2 55 { 56 57 61 62 65 66 76 public RAIDb2_LPRF(VirtualDatabase vdb, 77 WaitForCompletionPolicy waitForCompletionPolicy, 78 CreateTablePolicy createTablePolicy) throws Exception 79 { 80 super(vdb, waitForCompletionPolicy, createTablePolicy); 81 } 82 83 86 87 99 public ControllerResultSet statementExecuteQuery(SelectRequest request, 100 MetadataCache metadataCache) throws SQLException 101 { 102 try 104 { 105 vdb.acquireReadLockBackendLists(); 106 } 107 catch (InterruptedException e) 108 { 109 String msg = Translate.get( 110 "loadbalancer.backendlist.acquire.readlock.failed", e); 111 logger.error(msg); 112 throw new SQLException (msg); 113 } 114 115 DatabaseBackend backend = null; 117 try 120 { 121 ArrayList backends = vdb.getBackends(); 122 int size = backends.size(); 123 124 if (size == 0) 125 throw new NoMoreBackendException(Translate.get( 126 "loadbalancer.execute.no.backend.available", request.getId())); 127 128 int leastRequests = 0; 130 int enabledBackends = 0; 131 Collection tables = request.getFrom(); 132 if (tables == null) 133 throw new SQLException (Translate.get("loadbalancer.from.not.found", 134 request.getSqlShortForm(vdb.getSqlShortFormLength()))); 135 136 for (int i = 0; i < size; i++) 137 { 138 DatabaseBackend b = (DatabaseBackend) backends.get(i); 139 if (b.isReadEnabled()) 140 { 141 enabledBackends++; 142 if (b.hasTables(tables)) 143 { 144 int pending = b.getPendingRequests().size(); 145 if (((backend == null) || (pending < leastRequests))) 146 { 147 backend = b; 148 if (pending == 0) 149 break; else 151 leastRequests = pending; 152 } 153 } 154 } 155 } 156 157 if (backend == null) 158 { 159 if (enabledBackends == 0) 160 throw new NoMoreBackendException(Translate.get( 161 "loadbalancer.execute.no.backend.enabled", request.getId())); 162 else 163 throw new SQLException (Translate.get( 164 "loadbalancer.backend.no.required.tables", tables.toString())); 165 } 166 167 } 168 catch (RuntimeException e) 169 { 170 String msg = Translate.get("loadbalancer.request.failed.on.backend", 171 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 172 backend.getName(), e.getMessage()}); 173 logger.error(msg, e); 174 throw new SQLException (msg); 175 } 176 finally 177 { 178 vdb.releaseReadLockBackendLists(); 179 } 180 181 ControllerResultSet rs = null; 183 try 184 { 185 rs = executeReadRequestOnBackend(request, backend, metadataCache); 186 } 187 catch (UnreachableBackendException se) 188 { 189 return statementExecuteQuery(request, metadataCache); 191 } 192 catch (SQLException se) 193 { 194 String msg = Translate.get("loadbalancer.request.failed", new String []{ 195 String.valueOf(request.getId()), se.getMessage()}); 196 if (logger.isInfoEnabled()) 197 logger.info(msg); 198 throw new SQLException (msg); 199 } 200 catch (Throwable e) 201 { 202 String msg = Translate.get("loadbalancer.request.failed.on.backend", 203 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 204 backend.getName(), e.getMessage()}); 205 logger.error(msg, e); 206 throw new SQLException (msg); 207 } 208 209 return rs; 210 } 211 212 220 public ControllerResultSet readOnlyCallableStatementExecuteQuery( 221 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 222 { 223 return (ControllerResultSet) callStoredProcedure(proc, 224 CALLABLE_STATEMENT_EXECUTE_QUERY, metadataCache); 225 } 226 227 235 public ExecuteResult readOnlyCallableStatementExecute(StoredProcedure proc, 236 MetadataCache metadataCache) throws SQLException 237 { 238 return (ExecuteResult) callStoredProcedure(proc, 239 CALLABLE_STATEMENT_EXECUTE, metadataCache); 240 } 241 242 254 private Object callStoredProcedure(StoredProcedure proc, int callType, 255 MetadataCache metadataCache) throws SQLException 256 { 257 try 259 { 260 vdb.acquireReadLockBackendLists(); 261 } 262 catch (InterruptedException e) 263 { 264 String msg = Translate.get( 265 "loadbalancer.backendlist.acquire.readlock.failed", e); 266 logger.error(msg); 267 throw new SQLException (msg); 268 } 269 270 DatabaseBackend backend = null; 272 try 275 { 276 DatabaseBackend failedBackend = null; 277 SQLException failedException = null; 278 Object result = null; 279 do 280 { 281 ArrayList backends = vdb.getBackends(); 282 int size = backends.size(); 283 284 if (size == 0) 285 throw new NoMoreBackendException(Translate.get( 286 "loadbalancer.execute.no.backend.available", proc.getId())); 287 288 int leastRequests = 0; 290 int enabledBackends = 0; 291 292 for (int i = 0; i < size; i++) 293 { 294 DatabaseBackend b = (DatabaseBackend) backends.get(i); 295 if (b.isReadEnabled()) 296 { 297 enabledBackends++; 298 if (b.hasStoredProcedure(proc.getProcedureKey(), proc 299 .getNbOfParameters())) 300 { 301 int pending = b.getPendingRequests().size(); 302 if ((b != failedBackend) 303 && ((backend == null) || (pending < leastRequests))) 304 { 305 backend = b; 306 if (pending == 0) 307 break; else 309 leastRequests = pending; 310 } 311 } 312 } 313 } 314 315 if (backend == null) 316 { 317 if (enabledBackends == 0) 318 throw new SQLException (Translate 319 .get("loadbalancer.storedprocedure.backend.no.enabled", proc 320 .getId())); 321 else if (failedBackend == null) 322 throw new SQLException (Translate.get( 323 "loadbalancer.backend.no.required.storedprocedure", proc 324 .getProcedureKey())); 325 else 326 throw failedException; 328 } 329 330 boolean toDisable = false; 332 try 333 { 334 switch (callType) 335 { 336 case CALLABLE_STATEMENT_EXECUTE_QUERY : 337 result = executeStoredProcedureOnBackend(proc, true, backend, 338 metadataCache); 339 break; 340 case CALLABLE_STATEMENT_EXECUTE : 341 result = executeStoredProcedureOnBackend(proc, false, backend, 342 metadataCache); 343 break; 344 default : 345 throw new RuntimeException ("Unhandled call type " + callType 346 + " in executeLPRF"); 347 } 348 if (failedBackend != null) 349 { if (logger.isWarnEnabled()) 351 logger.warn(Translate.get("loadbalancer.storedprocedure.status", 352 new String []{String.valueOf(proc.getId()), backend.getName(), 353 failedBackend.getName()})); 354 toDisable = true; 355 } 356 } 357 catch (UnreachableBackendException se) 358 { 359 continue; 361 } 362 catch (SQLException se) 363 { 364 if (failedBackend != null) 365 { String msg = Translate.get( 367 "loadbalancer.storedprocedure.failed.twice", new String []{ 368 String.valueOf(proc.getId()), se.getMessage()}); 369 if (logger.isInfoEnabled()) 370 logger.info(msg); 371 throw new SQLException (msg); 372 } 373 else 374 { failedBackend = backend; 376 failedException = se; 377 if (logger.isInfoEnabled()) 378 logger.info(Translate.get( 379 "loadbalancer.storedprocedure.failed.on.backend", 380 new String []{ 381 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 382 backend.getName(), se.getMessage()})); 383 continue; 384 } 385 } 386 387 if (toDisable) 388 { try 391 { 392 if (logger.isWarnEnabled()) 393 logger.warn(Translate.get("loadbalancer.backend.disabling", 394 failedBackend.getName())); 395 disableBackend(failedBackend, true); 396 } 397 catch (SQLException ignore) 398 { 399 } 400 finally 401 { 402 failedBackend = null; } 404 } 405 } 406 while (failedBackend != null); 407 return result; 408 } 409 catch (RuntimeException e) 410 { 411 String msg = Translate.get( 412 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 413 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 414 backend.getName(), e.getMessage()}); 415 logger.fatal(msg, e); 416 throw new SQLException (msg); 417 } 418 finally 419 { 420 vdb.releaseReadLockBackendLists(); 421 } 422 } 423 424 427 428 433 public String getInformation() 434 { 435 int size = vdb.getBackends().size(); 437 438 if (size == 0) 439 return "RAIDb-2 Least Pending Requests First load balancer: !!!Warning!!! No backend nodes found\n"; 440 else 441 return "RAIDb-2 Least Pending Requests First load balancer (" + size 442 + " backends)\n"; 443 } 444 445 448 public String getRaidb2Xml() 449 { 450 return "<" + DatabasesXmlTags.ELT_RAIDb_2_LeastPendingRequestsFirst + "/>"; 451 } 452 } | Popular Tags |