1 36 37 package org.continuent.sequoia.controller.loadbalancer.paralleldb; 38 39 import java.sql.Connection ; 40 import java.sql.SQLException ; 41 import java.sql.Savepoint ; 42 import java.util.Hashtable ; 43 import java.util.List ; 44 45 import org.continuent.sequoia.common.exceptions.BadConnectionException; 46 import org.continuent.sequoia.common.exceptions.NoMoreBackendException; 47 import org.continuent.sequoia.common.exceptions.NoTransactionStartWhenDisablingException; 48 import org.continuent.sequoia.common.exceptions.SQLExceptionFactory; 49 import org.continuent.sequoia.common.exceptions.UnreachableBackendException; 50 import org.continuent.sequoia.common.i18n.Translate; 51 import org.continuent.sequoia.common.log.Trace; 52 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 53 import org.continuent.sequoia.controller.backend.DatabaseBackend; 54 import org.continuent.sequoia.controller.backend.result.ControllerResultSet; 55 import org.continuent.sequoia.controller.backend.result.ExecuteResult; 56 import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult; 57 import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult; 58 import org.continuent.sequoia.controller.cache.metadata.MetadataCache; 59 import org.continuent.sequoia.controller.connection.AbstractConnectionManager; 60 import org.continuent.sequoia.controller.connection.PooledConnection; 61 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer; 62 import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException; 63 import org.continuent.sequoia.controller.requestmanager.RAIDbLevels; 64 import org.continuent.sequoia.controller.requestmanager.TransactionMetaData; 65 import org.continuent.sequoia.controller.requests.AbstractRequest; 66 import org.continuent.sequoia.controller.requests.AbstractWriteRequest; 67 import org.continuent.sequoia.controller.requests.ParsingGranularities; 68 import org.continuent.sequoia.controller.requests.SelectRequest; 69 import org.continuent.sequoia.controller.requests.StoredProcedure; 70 import org.continuent.sequoia.controller.requests.UnknownReadRequest; 71 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase; 72 73 81 92 public abstract class ParallelDB extends AbstractLoadBalancer 93 { 94 private Hashtable backendPerTransactionId; 96 private int numberOfEnabledBackends = 0; 97 98 static Trace endUserLogger = Trace 99 .getLogger("org.continuent.sequoia.enduser"); 100 101 108 public ParallelDB(VirtualDatabase vdb) throws SQLException 109 { 110 super(vdb, RAIDbLevels.SingleDB, ParsingGranularities.NO_PARSING); 111 backendPerTransactionId = new Hashtable (); 112 } 113 114 118 126 public abstract DatabaseBackend chooseBackendForReadRequest( 127 AbstractRequest request) throws SQLException ; 128 129 137 public abstract DatabaseBackend chooseBackendForWriteRequest( 138 AbstractWriteRequest request) throws SQLException ; 139 140 144 public ControllerResultSet statementExecuteQuery(SelectRequest request, 145 MetadataCache metadataCache) throws SQLException 146 { 147 DatabaseBackend backend; 148 if (request.isAutoCommit()) 149 backend = chooseBackendForReadRequest(request); 150 else 151 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (request 152 .getTransactionId())); 153 154 if (backend == null) 155 throw new SQLException (Translate.get( 156 "loadbalancer.execute.no.backend.found", request.getSqlShortForm(vdb 157 .getSqlShortFormLength()))); 158 159 ControllerResultSet rs = null; 160 try 162 { 163 rs = executeStatementExecuteQueryOnBackend(request, backend, 164 metadataCache); 165 } 166 catch (UnreachableBackendException urbe) 167 { 168 if (recoveryLog != null) 170 recoveryLog.logRequestCompletion(request.getLogId(), false, request 171 .getExecTimeInMs()); 172 173 return statementExecuteQuery(request, metadataCache); 175 } 176 catch (SQLException se) 177 { 178 if (recoveryLog != null) 180 recoveryLog.logRequestCompletion(request.getLogId(), false, request 181 .getExecTimeInMs()); 182 183 String msg = Translate.get("loadbalancer.request.failed", new String []{ 184 String.valueOf(request.getId()), se.getMessage()}); 185 if (logger.isInfoEnabled()) 186 logger.info(msg); 187 throw new SQLException (msg); 188 } 189 catch (RuntimeException e) 190 { 191 if (recoveryLog != null) 193 recoveryLog.logRequestCompletion(request.getLogId(), false, request 194 .getExecTimeInMs()); 195 196 String msg = Translate.get("loadbalancer.request.failed.on.backend", 197 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 198 backend.getName(), e.getMessage()}); 199 logger.error(msg, e); 200 throw new SQLException (msg); 201 } 202 203 return rs; 204 } 205 206 209 public ExecuteUpdateResult statementExecuteUpdate(AbstractWriteRequest request) 210 throws AllBackendsFailedException, SQLException 211 { 212 handleMacros(request); 214 215 if (request.isLazyTransactionStart()) 217 this.vdb.getRequestManager().logLazyTransactionBegin( 218 request.getTransactionId()); 219 220 if (recoveryLog != null) 222 recoveryLog.logRequestExecuting(request); 223 224 DatabaseBackend backend; 225 if (request.isAutoCommit()) 226 backend = chooseBackendForWriteRequest(request); 227 else 228 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (request 229 .getTransactionId())); 230 231 if (backend == null) 232 throw new SQLException (Translate.get( 233 "loadbalancer.execute.no.backend.found", request.getSqlShortForm(vdb 234 .getSqlShortFormLength()))); 235 236 ExecuteUpdateResult result; 237 try 239 { 240 result = executeStatementExecuteUpdateOnBackend(request, backend); 241 } 242 catch (UnreachableBackendException urbe) 243 { 244 if (recoveryLog != null) 246 recoveryLog.logRequestCompletion(request.getLogId(), false, request 247 .getExecTimeInMs()); 248 249 return statementExecuteUpdate(request); 251 } 252 catch (SQLException se) 253 { 254 if (recoveryLog != null) 256 recoveryLog.logRequestCompletion(request.getLogId(), false, request 257 .getExecTimeInMs()); 258 259 String msg = Translate.get("loadbalancer.request.failed", new String []{ 260 String.valueOf(request.getId()), se.getMessage()}); 261 if (logger.isInfoEnabled()) 262 logger.info(msg); 263 throw new SQLException (msg); 264 } 265 catch (RuntimeException e) 266 { 267 if (recoveryLog != null) 269 recoveryLog.logRequestCompletion(request.getLogId(), false, request 270 .getExecTimeInMs()); 271 272 String msg = Translate.get("loadbalancer.request.failed.on.backend", 273 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 274 backend.getName(), e.getMessage()}); 275 logger.error(msg, e); 276 throw new SQLException (msg); 277 } 278 279 return result; 280 } 281 282 286 public GeneratedKeysResult statementExecuteUpdateWithKeys( 287 AbstractWriteRequest request, MetadataCache metadataCache) 288 throws AllBackendsFailedException, SQLException 289 { 290 handleMacros(request); 292 293 if (request.isLazyTransactionStart()) 295 this.vdb.getRequestManager().logLazyTransactionBegin( 296 request.getTransactionId()); 297 298 if (recoveryLog != null) 300 recoveryLog.logRequestExecuting(request); 301 302 DatabaseBackend backend; 303 if (request.isAutoCommit()) 304 backend = chooseBackendForWriteRequest(request); 305 else 306 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (request 307 .getTransactionId())); 308 309 if (backend == null) 310 throw new SQLException (Translate.get( 311 "loadbalancer.execute.no.backend.found", request.getSqlShortForm(vdb 312 .getSqlShortFormLength()))); 313 314 GeneratedKeysResult rs; 315 try 317 { 318 rs = executeStatementExecuteUpdateWithKeysOnBackend(request, backend, 319 metadataCache); 320 } 321 catch (UnreachableBackendException urbe) 322 { 323 if (recoveryLog != null) 325 recoveryLog.logRequestCompletion(request.getLogId(), false, request 326 .getExecTimeInMs()); 327 328 return statementExecuteUpdateWithKeys(request, metadataCache); 330 } 331 catch (SQLException se) 332 { 333 if (recoveryLog != null) 335 recoveryLog.logRequestCompletion(request.getLogId(), false, request 336 .getExecTimeInMs()); 337 338 String msg = Translate.get("loadbalancer.request.failed", new String []{ 339 String.valueOf(request.getId()), se.getMessage()}); 340 if (logger.isInfoEnabled()) 341 logger.info(msg); 342 throw new SQLException (msg); 343 } 344 catch (RuntimeException e) 345 { 346 if (recoveryLog != null) 348 recoveryLog.logRequestCompletion(request.getLogId(), false, request 349 .getExecTimeInMs()); 350 351 String msg = Translate.get("loadbalancer.request.failed.on.backend", 352 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 353 backend.getName(), e.getMessage()}); 354 logger.error(msg, e); 355 throw new SQLException (msg); 356 } 357 358 return rs; 359 } 360 361 365 public ExecuteResult statementExecute(AbstractRequest request, 366 MetadataCache metadataCache) throws SQLException , 367 AllBackendsFailedException 368 { 369 handleMacros(request); 371 372 if (request.isLazyTransactionStart()) 374 this.vdb.getRequestManager().logLazyTransactionBegin( 375 request.getTransactionId()); 376 377 if (recoveryLog != null) 379 recoveryLog.logRequestExecuting(request); 380 381 DatabaseBackend backend; 382 if (request.isAutoCommit()) 383 backend = chooseBackendForReadRequest(request); 384 else 385 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (request 386 .getTransactionId())); 387 388 if (backend == null) 389 throw new SQLException (Translate.get( 390 "loadbalancer.storedprocedure.no.backend.found", request 391 .getSqlShortForm(vdb.getSqlShortFormLength()))); 392 393 ExecuteResult rs = null; 394 try 396 { 397 rs = executeStatementExecuteOnBackend(request, backend, metadataCache); 398 } 399 catch (UnreachableBackendException urbe) 400 { 401 recoveryLog.logRequestCompletion(request.getLogId(), false, request 403 .getExecTimeInMs()); 404 405 return statementExecute(request, metadataCache); 407 } 408 catch (SQLException se) 409 { 410 recoveryLog.logRequestCompletion(request.getLogId(), false, request 412 .getExecTimeInMs()); 413 414 String msg = Translate.get("loadbalancer.storedprocedure.failed", 415 new String []{String.valueOf(request.getId()), se.getMessage()}); 416 if (logger.isInfoEnabled()) 417 logger.info(msg); 418 throw new SQLException (msg); 419 } 420 catch (RuntimeException e) 421 { 422 recoveryLog.logRequestCompletion(request.getLogId(), false, request 424 .getExecTimeInMs()); 425 426 String msg = Translate.get( 427 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 428 request.getSqlShortForm(vdb.getSqlShortFormLength()), 429 backend.getName(), e.getMessage()}); 430 logger.error(msg, e); 431 throw new SQLException (msg); 432 } 433 434 return rs; 435 } 436 437 441 public ControllerResultSet readOnlyCallableStatementExecuteQuery( 442 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 443 { 444 return callableStatementExecuteQuery(proc, metadataCache); 445 } 446 447 451 public ExecuteResult readOnlyCallableStatementExecute(StoredProcedure proc, 452 MetadataCache metadataCache) throws SQLException 453 { 454 return callableStatementExecute(proc, metadataCache); 455 } 456 457 461 public ControllerResultSet callableStatementExecuteQuery( 462 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 463 { 464 handleMacros(proc); 466 467 if (proc.isLazyTransactionStart()) 469 this.vdb.getRequestManager().logLazyTransactionBegin( 470 proc.getTransactionId()); 471 472 if (recoveryLog != null) 474 recoveryLog.logRequestExecuting(proc); 475 476 DatabaseBackend backend; 477 if (proc.isAutoCommit()) 478 backend = chooseBackendForReadRequest(proc); 479 else 480 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (proc 481 .getTransactionId())); 482 483 if (backend == null) 484 throw new SQLException (Translate.get( 485 "loadbalancer.storedprocedure.no.backend.found", proc 486 .getSqlShortForm(vdb.getSqlShortFormLength()))); 487 488 ControllerResultSet rs = null; 489 try 491 { 492 rs = executeCallableStatementExecuteQueryOnBackend(proc, backend, 493 metadataCache); 494 } 495 catch (UnreachableBackendException urbe) 496 { 497 if (recoveryLog != null) 499 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 500 .getExecTimeInMs()); 501 502 return callableStatementExecuteQuery(proc, metadataCache); 504 } 505 catch (SQLException se) 506 { 507 if (recoveryLog != null) 509 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 510 .getExecTimeInMs()); 511 512 String msg = Translate.get("loadbalancer.storedprocedure.failed", 513 new String []{String.valueOf(proc.getId()), se.getMessage()}); 514 if (logger.isInfoEnabled()) 515 logger.info(msg); 516 throw new SQLException (msg); 517 } 518 catch (RuntimeException e) 519 { 520 if (recoveryLog != null) 522 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 523 .getExecTimeInMs()); 524 525 String msg = Translate.get( 526 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 527 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 528 backend.getName(), e.getMessage()}); 529 logger.error(msg, e); 530 throw new SQLException (msg); 531 } 532 533 return rs; 534 } 535 536 539 public ExecuteUpdateResult callableStatementExecuteUpdate(StoredProcedure proc) 540 throws SQLException 541 { 542 handleMacros(proc); 544 545 if (proc.isLazyTransactionStart()) 547 this.vdb.getRequestManager().logLazyTransactionBegin( 548 proc.getTransactionId()); 549 550 if (recoveryLog != null) 552 recoveryLog.logRequestExecuting(proc); 553 554 DatabaseBackend backend; 555 if (proc.isAutoCommit()) 556 backend = chooseBackendForReadRequest(proc); 557 else 558 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (proc 559 .getTransactionId())); 560 561 if (backend == null) 562 throw new SQLException (Translate.get( 563 "loadbalancer.storedprocedure.no.backend.found", proc 564 .getSqlShortForm(vdb.getSqlShortFormLength()))); 565 566 ExecuteUpdateResult result; 567 try 569 { 570 result = executeCallableStatementExecuteUpdateOnBackend(proc, backend); 571 } 572 catch (UnreachableBackendException urbe) 573 { 574 if (recoveryLog != null) 576 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 577 .getExecTimeInMs()); 578 579 return callableStatementExecuteUpdate(proc); 581 } 582 catch (SQLException se) 583 { 584 if (recoveryLog != null) 586 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 587 .getExecTimeInMs()); 588 589 String msg = Translate.get("loadbalancer.storedprocedure.failed", 590 new String []{String.valueOf(proc.getId()), se.getMessage()}); 591 if (logger.isInfoEnabled()) 592 logger.info(msg); 593 throw new SQLException (msg); 594 } 595 catch (RuntimeException e) 596 { 597 if (recoveryLog != null) 599 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 600 .getExecTimeInMs()); 601 602 String msg = Translate.get( 603 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 604 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 605 backend.getName(), e.getMessage()}); 606 logger.error(msg, e); 607 throw new SQLException (msg); 608 } 609 610 return result; 611 } 612 613 617 public ExecuteResult callableStatementExecute(StoredProcedure proc, 618 MetadataCache metadataCache) throws SQLException 619 { 620 handleMacros(proc); 622 623 if (proc.isLazyTransactionStart()) 625 this.vdb.getRequestManager().logLazyTransactionBegin( 626 proc.getTransactionId()); 627 628 if (recoveryLog != null) 630 recoveryLog.logRequestExecuting(proc); 631 632 DatabaseBackend backend; 633 if (proc.isAutoCommit()) 634 backend = chooseBackendForReadRequest(proc); 635 else 636 backend = (DatabaseBackend) backendPerTransactionId.get(new Long (proc 637 .getTransactionId())); 638 639 if (backend == null) 640 throw new SQLException (Translate.get( 641 "loadbalancer.storedprocedure.no.backend.found", proc 642 .getSqlShortForm(vdb.getSqlShortFormLength()))); 643 644 ExecuteResult rs = null; 645 try 647 { 648 rs = executeCallableStatementExecuteOnBackend(proc, backend, 649 metadataCache); 650 } 651 catch (UnreachableBackendException urbe) 652 { 653 if (recoveryLog != null) 655 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 656 .getExecTimeInMs()); 657 658 ExecuteResult result = callableStatementExecute(proc, metadataCache); 660 661 return result; 662 } 663 catch (SQLException se) 664 { 665 if (recoveryLog != null) 667 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 668 .getExecTimeInMs()); 669 670 String msg = Translate.get("loadbalancer.storedprocedure.failed", 671 new String []{String.valueOf(proc.getId()), se.getMessage()}); 672 if (logger.isInfoEnabled()) 673 logger.info(msg); 674 throw new SQLException (msg); 675 } 676 catch (RuntimeException e) 677 { 678 if (recoveryLog != null) 680 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 681 .getExecTimeInMs()); 682 683 String msg = Translate.get( 684 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 685 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 686 backend.getName(), e.getMessage()}); 687 logger.error(msg, e); 688 throw new SQLException (msg); 689 } 690 691 return rs; 692 } 693 694 703 private ControllerResultSet executeStatementExecuteQueryOnBackend( 704 SelectRequest request, DatabaseBackend backend, 705 MetadataCache metadataCache) throws SQLException , 706 UnreachableBackendException 707 { 708 AbstractConnectionManager cm = backend.getConnectionManager(request 710 .getLogin()); 711 712 if (cm == null) 714 { 715 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 716 new String []{request.getLogin(), backend.getName()}); 717 logger.error(msg); 718 throw new SQLException (msg); 719 } 720 721 if (request.isAutoCommit()) 723 { 724 ControllerResultSet rs = null; 725 boolean badConnection; 726 do 727 { 728 badConnection = false; 729 PooledConnection pc = null; 731 try 732 { 733 pc = cm.retrieveConnectionInAutoCommit(request); 734 } 735 catch (UnreachableBackendException e1) 736 { 737 String msg = Translate.get( 738 "loadbalancer.backend.disabling.unreachable", backend.getName()); 739 logger.error(msg); 740 endUserLogger.error(msg); 741 disableBackend(backend, true); 742 throw new UnreachableBackendException(Translate.get( 743 "loadbalancer.backend.unreacheable", backend.getName())); 744 } 745 746 if (pc == null) 748 throw new SQLException (Translate.get( 749 "loadbalancer.backend.no.connection", backend.getName())); 750 751 try 753 { 754 rs = executeStatementExecuteQueryOnBackend(request, backend, null, pc 755 .getConnection(), metadataCache); 756 cm.releaseConnectionInAutoCommit(request, pc); 757 } 758 catch (BadConnectionException e) 759 { cm.deleteConnection(pc); 761 badConnection = true; 762 } 763 catch (Throwable e) 764 { 765 cm.releaseConnectionInAutoCommit(request, pc); 766 throw new SQLException (Translate.get( 767 "loadbalancer.request.failed.on.backend", new String []{ 768 request.getSqlShortForm(vdb.getSqlShortFormLength()), 769 backend.getName(), e.getMessage()})); 770 } 771 } 772 while (badConnection); 773 if (logger.isDebugEnabled()) 774 logger.debug(Translate.get("loadbalancer.execute.on", new String []{ 775 String.valueOf(request.getId()), backend.getName()})); 776 return rs; 777 } 778 else 779 { Connection c; 781 long tid = request.getTransactionId(); 782 783 try 784 { 785 c = backend 786 .getConnectionForTransactionAndLazyBeginIfNeeded(request, cm); 787 } 788 catch (UnreachableBackendException e1) 789 { 790 String msg = Translate.get( 791 "loadbalancer.backend.disabling.unreachable", backend.getName()); 792 logger.error(msg); 793 endUserLogger.error(msg); 794 disableBackend(backend, true); 795 throw new SQLException (Translate.get( 796 "loadbalancer.backend.unreacheable", backend.getName())); 797 } 798 catch (NoTransactionStartWhenDisablingException e) 799 { 800 String msg = Translate.get("loadbalancer.backend.is.disabling", 801 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 802 backend.getName()}); 803 logger.error(msg); 804 throw new SQLException (msg); 805 } 806 807 if (c == null) 809 throw new SQLException (Translate.get( 810 "loadbalancer.unable.retrieve.connection", new String []{ 811 String.valueOf(tid), backend.getName()})); 812 813 ControllerResultSet rs = null; 815 try 816 { 817 rs = executeStatementExecuteQueryOnBackend(request, backend, null, c, 818 metadataCache); 819 } 820 catch (BadConnectionException e) 821 { cm.deleteConnection(tid); 824 String msg = Translate.get( 825 "loadbalancer.backend.disabling.connection.failure", backend 826 .getName()); 827 logger.error(msg); 828 endUserLogger.error(msg); 829 disableBackend(backend, true); 830 throw new SQLException (msg); 831 } 832 catch (Throwable e) 833 { 834 throw new SQLException (Translate.get( 835 "loadbalancer.request.failed.on.backend", new String []{ 836 request.getSqlShortForm(vdb.getSqlShortFormLength()), 837 backend.getName(), e.getMessage()})); 838 } 839 if (logger.isDebugEnabled()) 840 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 841 new String []{String.valueOf(tid), String.valueOf(request.getId()), 842 backend.getName()})); 843 return rs; 844 } 845 } 846 847 855 private ExecuteUpdateResult executeStatementExecuteUpdateOnBackend( 856 AbstractWriteRequest request, DatabaseBackend backend) 857 throws SQLException , UnreachableBackendException 858 { 859 if (backend == null) 860 throw new NoMoreBackendException(Translate.get( 861 "loadbalancer.execute.no.backend.available", request.getId())); 862 863 try 864 { 865 AbstractConnectionManager cm = backend.getConnectionManager(request 866 .getLogin()); 867 if (request.isAutoCommit()) 868 { PooledConnection c = null; 870 try 871 { 872 c = cm.retrieveConnectionInAutoCommit(request); 873 } 874 catch (UnreachableBackendException e1) 875 { 876 String backendName = backend.getName(); 877 String msg = Translate.get( 878 "loadbalancer.backend.disabling.unreachable", backendName); 879 logger.error(msg); 880 endUserLogger.error(msg); 881 disableBackend(backend, true); 882 throw new UnreachableBackendException(Translate.get( 883 "loadbalancer.backend.unreacheable", backendName)); 884 } 885 886 if (c == null) 888 throw new UnreachableBackendException(Translate.get( 889 "loadbalancer.backend.no.connection", backend.getName())); 890 891 ExecuteUpdateResult result; 893 try 894 { 895 result = executeStatementExecuteUpdateOnBackend(request, backend, 896 null, c.getConnection()); 897 } 898 catch (Exception e) 899 { 900 throw new SQLException (Translate.get( 901 "loadbalancer.request.failed.on.backend", new String []{ 902 request.getSqlShortForm(vdb.getSqlShortFormLength()), 903 backend.getName(), e.getMessage()})); 904 } 905 finally 906 { 907 cm.releaseConnectionInAutoCommit(request, c); 908 } 909 return result; 910 } 911 else 912 { PooledConnection c = cm.retrieveConnectionForTransaction(request 914 .getTransactionId()); 915 916 if (c == null) 918 throw new SQLException (Translate.get( 919 "loadbalancer.unable.retrieve.connection", 920 new String []{String.valueOf(request.getTransactionId()), 921 backend.getName()})); 922 923 ExecuteUpdateResult result; 925 try 926 { 927 result = executeStatementExecuteUpdateOnBackend(request, backend, 928 null, c.getConnection()); 929 return result; 930 } 931 catch (Exception e) 932 { 933 throw new SQLException (Translate.get( 934 "loadbalancer.request.failed.on.backend", new String []{ 935 request.getSqlShortForm(vdb.getSqlShortFormLength()), 936 backend.getName(), e.getMessage()})); 937 } 938 } 939 } 940 catch (RuntimeException e) 941 { 942 String msg = Translate.get("loadbalancer.request.failed.on.backend", 943 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 944 backend.getName(), e.getMessage()}); 945 logger.fatal(msg, e); 946 throw new SQLException (msg); 947 } 948 } 949 950 960 private GeneratedKeysResult executeStatementExecuteUpdateWithKeysOnBackend( 961 AbstractWriteRequest request, DatabaseBackend backend, 962 MetadataCache metadataCache) throws SQLException , 963 UnreachableBackendException 964 { 965 if (backend == null) 966 throw new NoMoreBackendException(Translate.get( 967 "loadbalancer.execute.no.backend.available", request.getId())); 968 969 if (!backend.getDriverCompliance().supportGetGeneratedKeys()) 970 throw new SQLException (Translate.get( 971 "loadbalancer.backend.autogeneratedkeys.unsupported", backend 972 .getName())); 973 974 try 975 { 976 AbstractConnectionManager cm = backend.getConnectionManager(request 977 .getLogin()); 978 if (request.isAutoCommit()) 979 { PooledConnection c = null; 981 try 982 { 983 c = cm.retrieveConnectionInAutoCommit(request); 984 } 985 catch (UnreachableBackendException e1) 986 { 987 String backendName = backend.getName(); 988 String msg = Translate.get( 989 "loadbalancer.backend.disabling.unreachable", backendName); 990 logger.error(msg); 991 endUserLogger.error(msg); 992 disableBackend(backend, true); 993 throw new UnreachableBackendException(Translate.get( 994 "loadbalancer.backend.unreacheable", backendName)); 995 } 996 997 if (c == null) 999 throw new UnreachableBackendException(Translate.get( 1000 "loadbalancer.backend.no.connection", backend.getName())); 1001 1002 GeneratedKeysResult result; 1004 try 1005 { 1006 result = executeStatementExecuteUpdateWithKeysOnBackend(request, 1007 backend, null, c.getConnection(), metadataCache); 1008 } 1009 catch (Exception e) 1010 { 1011 throw new SQLException (Translate.get( 1012 "loadbalancer.request.failed.on.backend", new String []{ 1013 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1014 backend.getName(), e.getMessage()})); 1015 } 1016 finally 1017 { 1018 cm.releaseConnectionInAutoCommit(request, c); 1019 } 1020 return result; 1021 } 1022 else 1023 { PooledConnection c = cm.retrieveConnectionForTransaction(request 1025 .getTransactionId()); 1026 1027 if (c == null) 1029 throw new SQLException (Translate.get( 1030 "loadbalancer.unable.retrieve.connection", 1031 new String []{String.valueOf(request.getTransactionId()), 1032 backend.getName()})); 1033 1034 try 1036 { 1037 return executeStatementExecuteUpdateWithKeysOnBackend(request, 1038 backend, null, c.getConnection(), metadataCache); 1039 } 1040 catch (Exception e) 1041 { 1042 throw new SQLException (Translate.get( 1043 "loadbalancer.request.failed.on.backend", new String []{ 1044 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1045 backend.getName(), e.getMessage()})); 1046 } 1047 } 1048 } 1049 catch (RuntimeException e) 1050 { 1051 String msg = Translate.get("loadbalancer.request.failed", 1052 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 1053 e.getMessage()}); 1054 logger.fatal(msg, e); 1055 endUserLogger.fatal(msg); 1056 throw new SQLException (msg); 1057 } 1058 } 1059 1060 1069 private ExecuteResult executeStatementExecuteOnBackend( 1070 AbstractRequest request, DatabaseBackend backend, 1071 MetadataCache metadataCache) throws SQLException , 1072 UnreachableBackendException 1073 { 1074 AbstractConnectionManager cm = backend.getConnectionManager(request 1076 .getLogin()); 1077 1078 if (cm == null) 1080 { 1081 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 1082 new String []{request.getLogin(), backend.getName()}); 1083 logger.error(msg); 1084 throw new SQLException (msg); 1085 } 1086 1087 if (request.isAutoCommit()) 1089 { 1090 PooledConnection c = null; 1092 try 1093 { 1094 c = cm.retrieveConnectionInAutoCommit(request); 1095 } 1096 catch (UnreachableBackendException e1) 1097 { 1098 String msg = Translate.get( 1099 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1100 logger.error(msg); 1101 endUserLogger.error(msg); 1102 disableBackend(backend, true); 1103 throw new UnreachableBackendException(Translate.get( 1104 "loadbalancer.backend.unreacheable", backend.getName())); 1105 } 1106 1107 if (c == null) 1109 throw new UnreachableBackendException(Translate.get( 1110 "loadbalancer.backend.no.connection", backend.getName())); 1111 1112 ExecuteResult rs = null; 1114 try 1115 { 1116 rs = AbstractLoadBalancer.executeStatementExecuteOnBackend(request, 1117 backend, null, c.getConnection(), metadataCache); 1118 } 1119 catch (Exception e) 1120 { 1121 throw new SQLException (Translate.get( 1122 "loadbalancer.request.failed.on.backend", new String []{ 1123 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1124 backend.getName(), e.getMessage()})); 1125 } 1126 finally 1127 { 1128 cm.releaseConnectionInAutoCommit(request, c); 1129 } 1130 if (logger.isDebugEnabled()) 1131 logger.debug(Translate.get("loadbalancer.request.on", new String []{ 1132 String.valueOf(request.getId()), backend.getName()})); 1133 return rs; 1134 } 1135 else 1136 { Connection c; 1138 long tid = request.getTransactionId(); 1139 1140 try 1141 { 1142 c = backend 1143 .getConnectionForTransactionAndLazyBeginIfNeeded(request, cm); 1144 } 1145 catch (UnreachableBackendException e1) 1146 { 1147 String msg = Translate.get( 1148 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1149 logger.error(msg); 1150 endUserLogger.error(msg); 1151 disableBackend(backend, true); 1152 throw new SQLException (Translate.get( 1153 "loadbalancer.backend.unreacheable", backend.getName())); 1154 } 1155 catch (NoTransactionStartWhenDisablingException e) 1156 { 1157 String msg = Translate.get("loadbalancer.backend.is.disabling", 1158 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 1159 backend.getName()}); 1160 logger.error(msg); 1161 throw new SQLException (msg); 1162 } 1163 1164 if (c == null) 1166 throw new SQLException (Translate.get( 1167 "loadbalancer.unable.retrieve.connection", new String []{ 1168 String.valueOf(tid), backend.getName()})); 1169 1170 ExecuteResult rs; 1172 try 1173 { 1174 rs = AbstractLoadBalancer.executeStatementExecuteOnBackend(request, 1175 backend, null, c, metadataCache); 1176 } 1177 catch (Exception e) 1178 { 1179 throw new SQLException (Translate.get( 1180 "loadbalancer.request.failed.on.backend", new String []{ 1181 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1182 backend.getName(), e.getMessage()})); 1183 } 1184 if (logger.isDebugEnabled()) 1185 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 1186 new String []{String.valueOf(tid), String.valueOf(request.getId()), 1187 backend.getName()})); 1188 return rs; 1189 } 1190 } 1191 1192 1201 private ControllerResultSet executeCallableStatementExecuteQueryOnBackend( 1202 StoredProcedure proc, DatabaseBackend backend, MetadataCache metadataCache) 1203 throws SQLException , UnreachableBackendException 1204 { 1205 AbstractConnectionManager cm = backend 1207 .getConnectionManager(proc.getLogin()); 1208 1209 if (cm == null) 1211 { 1212 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 1213 new String []{proc.getLogin(), backend.getName()}); 1214 logger.error(msg); 1215 throw new SQLException (msg); 1216 } 1217 1218 if (proc.isAutoCommit()) 1220 { 1221 PooledConnection c = null; 1223 try 1224 { 1225 c = cm.retrieveConnectionInAutoCommit(proc); 1226 } 1227 catch (UnreachableBackendException e1) 1228 { 1229 String msg = Translate.get( 1230 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1231 logger.error(msg); 1232 endUserLogger.error(msg); 1233 disableBackend(backend, true); 1234 throw new UnreachableBackendException(Translate.get( 1235 "loadbalancer.backend.unreacheable", backend.getName())); 1236 } 1237 1238 if (c == null) 1240 throw new UnreachableBackendException(Translate.get( 1241 "loadbalancer.backend.no.connection", backend.getName())); 1242 1243 ControllerResultSet rs = null; 1245 try 1246 { 1247 rs = AbstractLoadBalancer 1248 .executeCallableStatementExecuteQueryOnBackend(proc, backend, null, 1249 c.getConnection(), metadataCache); 1250 } 1251 catch (Exception e) 1252 { 1253 throw new SQLException (Translate.get( 1254 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1255 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1256 backend.getName(), e.getMessage()})); 1257 } 1258 finally 1259 { 1260 cm.releaseConnectionInAutoCommit(proc, c); 1261 } 1262 if (logger.isDebugEnabled()) 1263 logger.debug(Translate.get("loadbalancer.storedprocedure.on", 1264 new String []{String.valueOf(proc.getId()), backend.getName()})); 1265 return rs; 1266 } 1267 else 1268 { Connection c; 1270 long tid = proc.getTransactionId(); 1271 1272 try 1273 { 1274 c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(proc, cm); 1275 } 1276 catch (UnreachableBackendException e1) 1277 { 1278 String msg = Translate.get( 1279 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1280 logger.error(msg); 1281 endUserLogger.error(msg); 1282 disableBackend(backend, true); 1283 throw new SQLException (Translate.get( 1284 "loadbalancer.backend.unreacheable", backend.getName())); 1285 } 1286 catch (NoTransactionStartWhenDisablingException e) 1287 { 1288 String msg = Translate.get("loadbalancer.backend.is.disabling", 1289 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1290 backend.getName()}); 1291 logger.error(msg); 1292 throw new SQLException (msg); 1293 } 1294 1295 if (c == null) 1297 throw new SQLException (Translate.get( 1298 "loadbalancer.unable.retrieve.connection", new String []{ 1299 String.valueOf(tid), backend.getName()})); 1300 1301 ControllerResultSet rs; 1303 try 1304 { 1305 rs = AbstractLoadBalancer 1306 .executeCallableStatementExecuteQueryOnBackend(proc, backend, null, 1307 c, metadataCache); 1308 } 1309 catch (Exception e) 1310 { 1311 throw new SQLException (Translate.get( 1312 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1313 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1314 backend.getName(), e.getMessage()})); 1315 } 1316 if (logger.isDebugEnabled()) 1317 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 1318 new String []{String.valueOf(tid), String.valueOf(proc.getId()), 1319 backend.getName()})); 1320 return rs; 1321 } 1322 } 1323 1324 1332 private ExecuteUpdateResult executeCallableStatementExecuteUpdateOnBackend( 1333 StoredProcedure proc, DatabaseBackend backend) throws SQLException , 1334 UnreachableBackendException 1335 { 1336 AbstractConnectionManager cm = backend 1338 .getConnectionManager(proc.getLogin()); 1339 1340 if (cm == null) 1342 { 1343 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 1344 new String []{proc.getLogin(), backend.getName()}); 1345 logger.error(msg); 1346 throw new SQLException (msg); 1347 } 1348 1349 if (proc.isAutoCommit()) 1351 { 1352 PooledConnection c = null; 1354 try 1355 { 1356 c = cm.retrieveConnectionInAutoCommit(proc); 1357 } 1358 catch (UnreachableBackendException e1) 1359 { 1360 String msg = Translate.get( 1361 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1362 logger.error(msg); 1363 endUserLogger.error(msg); 1364 disableBackend(backend, true); 1365 throw new UnreachableBackendException(Translate.get( 1366 "loadbalancer.backend.unreacheable", backend.getName())); 1367 } 1368 1369 if (c == null) 1371 throw new UnreachableBackendException(Translate.get( 1372 "loadbalancer.backend.no.connection", backend.getName())); 1373 1374 ExecuteUpdateResult result; 1376 try 1377 { 1378 result = AbstractLoadBalancer 1379 .executeCallableStatementExecuteUpdateOnBackend(proc, backend, 1380 null, c.getConnection()); 1381 1382 } 1385 catch (Exception e) 1386 { 1387 throw new SQLException (Translate.get( 1388 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1389 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1390 backend.getName(), e.getMessage()})); 1391 } 1392 finally 1393 { 1394 cm.releaseConnectionInAutoCommit(proc, c); 1395 } 1396 if (logger.isDebugEnabled()) 1397 logger.debug(Translate.get("loadbalancer.storedprocedure.on", 1398 new String []{String.valueOf(proc.getId()), backend.getName()})); 1399 return result; 1400 } 1401 else 1402 { Connection c; 1404 long tid = proc.getTransactionId(); 1405 1406 try 1407 { 1408 c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(proc, cm); 1409 } 1410 catch (UnreachableBackendException e1) 1411 { 1412 String msg = Translate.get( 1413 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1414 logger.error(msg); 1415 endUserLogger.error(msg); 1416 disableBackend(backend, true); 1417 throw new SQLException (Translate.get( 1418 "loadbalancer.backend.unreacheable", backend.getName())); 1419 } 1420 catch (NoTransactionStartWhenDisablingException e) 1421 { 1422 String msg = Translate.get("loadbalancer.backend.is.disabling", 1423 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1424 backend.getName()}); 1425 logger.error(msg); 1426 throw new SQLException (msg); 1427 } 1428 1429 if (c == null) 1431 throw new SQLException (Translate.get( 1432 "loadbalancer.unable.retrieve.connection", new String []{ 1433 String.valueOf(tid), backend.getName()})); 1434 1435 ExecuteUpdateResult result; 1437 try 1438 { 1439 result = AbstractLoadBalancer 1440 .executeCallableStatementExecuteUpdateOnBackend(proc, backend, 1441 null, c); 1442 1443 } 1446 catch (Exception e) 1447 { 1448 throw new SQLException (Translate.get( 1449 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1450 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1451 backend.getName(), e.getMessage()})); 1452 } 1453 if (logger.isDebugEnabled()) 1454 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 1455 new String []{String.valueOf(tid), String.valueOf(proc.getId()), 1456 backend.getName()})); 1457 return result; 1458 } 1459 } 1460 1461 1471 private ExecuteResult executeCallableStatementExecuteOnBackend( 1472 StoredProcedure proc, DatabaseBackend backend, MetadataCache metadataCache) 1473 throws SQLException , UnreachableBackendException 1474 { 1475 AbstractConnectionManager cm = backend 1477 .getConnectionManager(proc.getLogin()); 1478 1479 if (cm == null) 1481 { 1482 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 1483 new String []{proc.getLogin(), backend.getName()}); 1484 logger.error(msg); 1485 throw new SQLException (msg); 1486 } 1487 1488 if (proc.isAutoCommit()) 1490 { 1491 PooledConnection c = null; 1493 try 1494 { 1495 c = cm.retrieveConnectionInAutoCommit(proc); 1496 } 1497 catch (UnreachableBackendException e1) 1498 { 1499 String msg = Translate.get( 1500 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1501 logger.error(msg); 1502 endUserLogger.error(msg); 1503 disableBackend(backend, true); 1504 throw new UnreachableBackendException(Translate.get( 1505 "loadbalancer.backend.unreacheable", backend.getName())); 1506 } 1507 1508 if (c == null) 1510 throw new UnreachableBackendException(Translate.get( 1511 "loadbalancer.backend.no.connection", backend.getName())); 1512 1513 ExecuteResult rs = null; 1515 try 1516 { 1517 rs = AbstractLoadBalancer.executeCallableStatementExecuteOnBackend( 1518 proc, backend, null, c.getConnection(), metadataCache); 1519 } 1520 catch (Exception e) 1521 { 1522 throw new SQLException (Translate.get( 1523 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1524 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1525 backend.getName(), e.getMessage()})); 1526 } 1527 finally 1528 { 1529 cm.releaseConnectionInAutoCommit(proc, c); 1530 } 1531 if (logger.isDebugEnabled()) 1532 logger.debug(Translate.get("loadbalancer.storedprocedure.on", 1533 new String []{String.valueOf(proc.getId()), backend.getName()})); 1534 return rs; 1535 } 1536 else 1537 { Connection c; 1539 long tid = proc.getTransactionId(); 1540 1541 try 1542 { 1543 c = backend.getConnectionForTransactionAndLazyBeginIfNeeded(proc, cm); 1544 } 1545 catch (UnreachableBackendException e1) 1546 { 1547 String msg = Translate.get( 1548 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1549 logger.error(msg); 1550 endUserLogger.error(msg); 1551 disableBackend(backend, true); 1552 throw new SQLException (Translate.get( 1553 "loadbalancer.backend.unreacheable", backend.getName())); 1554 } 1555 catch (NoTransactionStartWhenDisablingException e) 1556 { 1557 String msg = Translate.get("loadbalancer.backend.is.disabling", 1558 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1559 backend.getName()}); 1560 logger.error(msg); 1561 throw new SQLException (msg); 1562 } 1563 1564 if (c == null) 1566 throw new SQLException (Translate.get( 1567 "loadbalancer.unable.retrieve.connection", new String []{ 1568 String.valueOf(tid), backend.getName()})); 1569 1570 ExecuteResult rs; 1572 try 1573 { 1574 rs = AbstractLoadBalancer.executeCallableStatementExecuteOnBackend( 1575 proc, backend, null, c, metadataCache); 1576 } 1577 catch (Exception e) 1578 { 1579 throw new SQLException (Translate.get( 1580 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 1581 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1582 backend.getName(), e.getMessage()})); 1583 } 1584 if (logger.isDebugEnabled()) 1585 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 1586 new String []{String.valueOf(tid), String.valueOf(proc.getId()), 1587 backend.getName()})); 1588 return rs; 1589 } 1590 } 1591 1592 1595 public ControllerResultSet getPreparedStatementGetMetaData( 1596 AbstractRequest request) throws SQLException 1597 { 1598 DatabaseBackend backend = chooseBackendForReadRequest(request); 1599 1600 if (backend == null) 1601 throw new NoMoreBackendException(Translate.get( 1602 "loadbalancer.execute.no.backend.enabled", request.getId())); 1603 1604 AbstractConnectionManager cm = backend.getConnectionManager(request 1606 .getLogin()); 1607 1608 if (cm == null) 1610 { 1611 String msg = Translate.get("loadbalancer.connectionmanager.not.found", 1612 new String []{request.getLogin(), backend.getName()}); 1613 logger.error(msg); 1614 throw new SQLException (msg); 1615 } 1616 1617 if (request.isAutoCommit()) 1619 { 1620 ControllerResultSet rs = null; 1621 boolean badConnection; 1622 do 1623 { 1624 badConnection = false; 1625 PooledConnection c = null; 1627 try 1628 { 1629 c = cm.retrieveConnectionInAutoCommit(request); 1630 } 1631 catch (UnreachableBackendException e1) 1632 { 1633 String msg = Translate.get( 1634 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1635 logger.error(msg); 1636 endUserLogger.error(msg); 1637 disableBackend(backend, true); 1638 return getPreparedStatementGetMetaData(request); 1640 } 1641 1642 if (c == null) 1644 throw new SQLException (Translate.get( 1645 "loadbalancer.backend.no.connection", backend.getName())); 1646 1647 try 1649 { 1650 rs = preparedStatementGetMetaDataOnBackend( 1651 request.getSqlOrTemplate(), backend, c.getConnection()); 1652 cm.releaseConnectionInAutoCommit(request, c); 1653 } 1654 catch (SQLException e) 1655 { 1656 cm.releaseConnectionInAutoCommit(request, c); 1657 throw SQLExceptionFactory.getSQLException(e, Translate.get( 1658 "loadbalancer.request.failed.on.backend", new String []{ 1659 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1660 backend.getName(), e.getMessage()})); 1661 } 1662 catch (BadConnectionException e) 1663 { cm.deleteConnection(c); 1665 badConnection = true; 1666 } 1667 catch (Throwable e) 1668 { 1669 cm.releaseConnectionInAutoCommit(request, c); 1670 throw new SQLException (Translate.get( 1671 "loadbalancer.request.failed.on.backend", new String []{ 1672 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1673 backend.getName(), e.getMessage()})); 1674 } 1675 } 1676 while (badConnection); 1677 if (logger.isDebugEnabled()) 1678 logger.debug(Translate.get("loadbalancer.execute.on", new String []{ 1679 String.valueOf(request.getId()), backend.getName()})); 1680 return rs; 1681 } 1682 else 1683 { Connection c; 1685 long tid = request.getTransactionId(); 1686 1687 try 1688 { 1689 c = backend 1690 .getConnectionForTransactionAndLazyBeginIfNeeded(request, cm); 1691 } 1692 catch (UnreachableBackendException e1) 1693 { 1694 String msg = Translate.get( 1695 "loadbalancer.backend.disabling.unreachable", backend.getName()); 1696 logger.error(msg); 1697 endUserLogger.error(msg); 1698 disableBackend(backend, true); 1699 throw new SQLException (Translate.get( 1700 "loadbalancer.backend.unreacheable", backend.getName())); 1701 } 1702 catch (NoTransactionStartWhenDisablingException e) 1703 { 1704 String msg = Translate.get("loadbalancer.backend.is.disabling", 1705 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 1706 backend.getName()}); 1707 logger.error(msg); 1708 throw new SQLException (msg); 1709 } 1710 1711 if (c == null) 1713 throw new SQLException (Translate.get( 1714 "loadbalancer.unable.retrieve.connection", new String []{ 1715 String.valueOf(tid), backend.getName()})); 1716 1717 ControllerResultSet rs = null; 1719 try 1720 { 1721 rs = preparedStatementGetMetaDataOnBackend(request.getSqlOrTemplate(), 1722 backend, c); 1723 } 1724 catch (SQLException e) 1725 { 1726 throw e; 1727 } 1728 catch (BadConnectionException e) 1729 { cm.deleteConnection(tid); 1732 String msg = Translate.get( 1733 "loadbalancer.backend.disabling.connection.failure", backend 1734 .getName()); 1735 logger.error(msg); 1736 endUserLogger.error(msg); 1737 disableBackend(backend, true); 1738 throw new SQLException (msg); 1739 } 1740 catch (Throwable e) 1741 { 1742 throw new SQLException (Translate.get( 1743 "loadbalancer.request.failed.on.backend", new String []{ 1744 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1745 backend.getName(), e.getMessage()})); 1746 } 1747 if (logger.isDebugEnabled()) 1748 logger.debug(Translate.get("loadbalancer.execute.transaction.on", 1749 new String []{String.valueOf(tid), String.valueOf(request.getId()), 1750 backend.getName()})); 1751 return rs; 1752 } 1753 } 1754 1755 1759 1762 public void abort(TransactionMetaData tm) throws SQLException 1763 { 1764 rollback(tm); 1765 } 1766 1767 1770 public void begin(TransactionMetaData tm) throws SQLException 1771 { 1772 Long lTid = new Long (tm.getTransactionId()); 1773 if (backendPerTransactionId.containsKey(lTid)) 1774 throw new SQLException (Translate.get( 1775 "loadbalancer.transaction.already.started", lTid.toString())); 1776 1777 DatabaseBackend backend = chooseBackendForReadRequest(new UnknownReadRequest( 1778 "begin", false, 0, "\n")); 1779 backendPerTransactionId.put(lTid, backend); 1780 backend.startTransaction(lTid); 1781 } 1782 1783 1786 public void commit(TransactionMetaData tm) throws SQLException 1787 { 1788 long tid = tm.getTransactionId(); 1789 Long lTid = new Long (tid); 1790 DatabaseBackend db = (DatabaseBackend) backendPerTransactionId.remove(lTid); 1791 1792 AbstractConnectionManager cm = db.getConnectionManager(tm.getLogin()); 1793 PooledConnection pc = cm.retrieveConnectionForTransaction(tid); 1794 1795 long logId = 0; 1796 if (recoveryLog != null) 1798 logId = recoveryLog.logCommit(tm); 1799 1800 if (pc == null) 1802 { db.stopTransaction(lTid); 1804 1805 throw new SQLException (Translate.get( 1806 "loadbalancer.unable.retrieve.connection", new String []{ 1807 String.valueOf(tid), db.getName()})); 1808 } 1809 1810 try 1812 { 1813 Connection c = pc.getConnection(); 1814 c.commit(); 1815 c.setAutoCommit(true); 1816 } 1817 catch (Exception e) 1818 { 1819 if (recoveryLog != null) 1821 recoveryLog.logRequestCompletion(logId, false, 0); 1822 1823 String msg = Translate.get("loadbalancer.commit.failed", new String []{ 1824 String.valueOf(tid), db.getName(), e.getMessage()}); 1825 logger.error(msg); 1826 throw new SQLException (msg); 1827 } 1828 finally 1829 { 1830 cm.releaseConnectionForTransaction(tid); 1831 db.stopTransaction(lTid); 1832 } 1833 } 1834 1835 1838 public void rollback(TransactionMetaData tm) throws SQLException 1839 { 1840 long tid = tm.getTransactionId(); 1841 Long lTid = new Long (tid); 1842 DatabaseBackend db = (DatabaseBackend) backendPerTransactionId.remove(lTid); 1843 1844 AbstractConnectionManager cm = db.getConnectionManager(tm.getLogin()); 1845 PooledConnection pc = cm.retrieveConnectionForTransaction(tid); 1846 1847 long logId = 0; 1848 if (recoveryLog != null) 1850 logId = recoveryLog.logRollback(tm); 1851 1852 if (pc == null) 1854 { db.stopTransaction(lTid); 1856 1857 throw new SQLException (Translate.get( 1858 "loadbalancer.unable.retrieve.connection", new String []{ 1859 String.valueOf(tid), db.getName()})); 1860 } 1861 1862 try 1864 { 1865 Connection c = pc.getConnection(); 1866 c.rollback(); 1867 1868 c.setAutoCommit(true); 1869 } 1870 catch (Exception e) 1871 { 1872 if (recoveryLog != null) 1874 recoveryLog.logRequestCompletion(logId, false, 0); 1875 1876 String msg = Translate.get("loadbalancer.rollback.failed", new String []{ 1877 String.valueOf(tid), db.getName(), e.getMessage()}); 1878 logger.error(msg); 1879 throw new SQLException (msg); 1880 } 1881 finally 1882 { 1883 cm.releaseConnectionForTransaction(tid); 1884 db.stopTransaction(lTid); 1885 } 1886 } 1887 1888 1895 public void rollbackToSavepoint(TransactionMetaData tm, String savepointName) 1896 throws SQLException 1897 { 1898 long tid = tm.getTransactionId(); 1899 Long lTid = new Long (tid); 1900 DatabaseBackend db = (DatabaseBackend) backendPerTransactionId.remove(lTid); 1901 1902 AbstractConnectionManager cm = db.getConnectionManager(tm.getLogin()); 1903 PooledConnection c = cm.retrieveConnectionForTransaction(tid); 1904 1905 long logId = 0; 1906 if (recoveryLog != null) 1908 logId = recoveryLog.logRollbackToSavepoint(tm, savepointName); 1909 1910 if (c == null) 1912 { db.stopTransaction(lTid); 1914 1915 throw new SQLException (Translate.get( 1916 "loadbalancer.unable.retrieve.connection", new String []{ 1917 String.valueOf(tid), db.getName()})); 1918 } 1919 1920 Savepoint savepoint = db.getSavepoint(lTid, savepointName); 1922 if (savepoint == null) 1923 { 1924 throw new SQLException (Translate.get( 1925 "loadbalancer.unable.retrieve.savepoint", new String []{savepointName, 1926 String.valueOf(tid), db.getName()})); 1927 } 1928 1929 try 1931 { 1932 c.getConnection().rollback(savepoint); 1933 } 1934 catch (Exception e) 1935 { 1936 if (recoveryLog != null) 1938 recoveryLog.logRequestCompletion(logId, false, 0); 1939 1940 String msg = Translate.get("loadbalancer.rollbacksavepoint.failed", 1941 new String []{savepointName, String.valueOf(tid), db.getName(), 1942 e.getMessage()}); 1943 logger.error(msg); 1944 throw new SQLException (msg); 1945 } 1946 } 1947 1948 1955 public void releaseSavepoint(TransactionMetaData tm, String savepointName) 1956 throws SQLException 1957 { 1958 long tid = tm.getTransactionId(); 1959 Long lTid = new Long (tid); 1960 1961 DatabaseBackend db = (DatabaseBackend) backendPerTransactionId.get(lTid); 1962 AbstractConnectionManager cm = db.getConnectionManager(tm.getLogin()); 1963 PooledConnection c = cm.retrieveConnectionForTransaction(tid); 1964 1965 long logId = 0; 1966 if (recoveryLog != null) 1968 logId = recoveryLog.logReleaseSavepoint(tm, savepointName); 1969 1970 if (c == null) 1972 { db.stopTransaction(lTid); 1974 1975 throw new SQLException (Translate.get( 1976 "loadbalancer.unable.retrieve.connection", new String []{ 1977 String.valueOf(tid), db.getName()})); 1978 } 1979 1980 Savepoint savepoint = db.getSavepoint(lTid, savepointName); 1982 if (savepoint == null) 1983 { 1984 throw new SQLException (Translate.get( 1985 "loadbalancer.unable.retrieve.savepoint", new String []{ 1986 String.valueOf(tid), savepointName, db.getName()})); 1987 } 1988 1989 try 1991 { 1992 c.getConnection().releaseSavepoint(savepoint); 1993 } 1994 catch (Exception e) 1995 { 1996 if (recoveryLog != null) 1998 recoveryLog.logRequestCompletion(logId, false, 0); 1999 2000 String msg = Translate.get("loadbalancer.releasesavepoint.failed", 2001 new String []{savepointName, String.valueOf(tid), db.getName(), 2002 e.getMessage()}); 2003 logger.error(msg); 2004 throw new SQLException (msg); 2005 } 2006 finally 2007 { 2008 db.removeSavepoint(lTid, savepoint); 2009 } 2010 } 2011 2012 2019 public void setSavepoint(TransactionMetaData tm, String savepointName) 2020 throws SQLException 2021 { 2022 long tid = tm.getTransactionId(); 2023 Long lTid = new Long (tid); 2024 2025 DatabaseBackend db = (DatabaseBackend) backendPerTransactionId.get(lTid); 2026 AbstractConnectionManager cm = db.getConnectionManager(tm.getLogin()); 2027 PooledConnection c = cm.retrieveConnectionForTransaction(tid); 2028 2029 long logId = 0; 2030 if (recoveryLog != null) 2032 logId = recoveryLog.logSetSavepoint(tm, savepointName); 2033 2034 if (c == null) 2036 { db.stopTransaction(lTid); 2038 2039 throw new SQLException (Translate.get( 2040 "loadbalancer.unable.retrieve.connection", new String []{ 2041 String.valueOf(tid), db.getName()})); 2042 } 2043 2044 Savepoint savepoint = null; 2046 try 2047 { 2048 savepoint = c.getConnection().setSavepoint(savepointName); 2049 } 2050 catch (Exception e) 2051 { 2052 if (recoveryLog != null) 2054 recoveryLog.logRequestCompletion(logId, false, 0); 2055 2056 String msg = Translate.get("loadbalancer.setsavepoint.failed", 2057 new String []{savepointName, String.valueOf(tid), db.getName(), 2058 e.getMessage()}); 2059 logger.error(msg); 2060 throw new SQLException (msg); 2061 } 2062 finally 2063 { 2064 if (savepoint != null) 2065 db.addSavepoint(lTid, savepoint); 2066 } 2067 } 2068 2069 2073 public void closePersistentConnection(String login, 2074 long persistentConnectionId) throws SQLException 2075 { 2076 try 2077 { 2078 vdb.acquireReadLockBackendLists(); 2079 } 2080 catch (InterruptedException e) 2081 { 2082 String msg = Translate.get( 2083 "loadbalancer.backendlist.acquire.readlock.failed", e); 2084 logger.error(msg); 2085 } 2086 int size = vdb.getBackends().size(); 2087 List backends = vdb.getBackends(); 2088 for (int i = 0; i < size; i++) 2089 { 2090 DatabaseBackend backend = (DatabaseBackend) backends.get(i); 2091 AbstractConnectionManager cm = backend.getConnectionManager(login); 2092 if (cm != null) 2093 { 2094 cm.releasePersistentConnectionInAutoCommit(persistentConnectionId); 2095 backend.removePersistentConnection(persistentConnectionId); 2096 } 2097 } 2098 vdb.releaseReadLockBackendLists(); 2099 } 2100 2101 2105 public void openPersistentConnection(String login, long persistentConnectionId) 2106 throws SQLException 2107 { 2108 AbstractRequest request = new UnknownReadRequest("", false, 0, ""); 2110 request.setLogin(login); 2111 request.setPersistentConnection(true); 2112 request.setPersistentConnectionId(persistentConnectionId); 2113 2114 try 2115 { 2116 vdb.acquireReadLockBackendLists(); 2117 } 2118 catch (InterruptedException e) 2119 { 2120 String msg = Translate.get( 2121 "loadbalancer.backendlist.acquire.readlock.failed", e); 2122 logger.error(msg); 2123 } 2124 int size = vdb.getBackends().size(); 2125 List backends = vdb.getBackends(); 2126 for (int i = 0; i < size; i++) 2127 { 2128 DatabaseBackend backend = (DatabaseBackend) backends.get(i); 2129 AbstractConnectionManager cm = backend.getConnectionManager(login); 2130 if (cm == null) 2131 { 2132 logger.warn("Failed to open persistent connection " 2133 + persistentConnectionId + " on backend " + backend.getName()); 2134 continue; 2135 } 2136 try 2137 { 2138 PooledConnection c = cm.retrieveConnectionInAutoCommit(request); 2140 backend.addPersistentConnection(request.getPersistentConnectionId(), c); 2141 } 2142 catch (UnreachableBackendException e) 2143 { 2144 logger.warn("Failed to open persistent connection " 2145 + persistentConnectionId + " on backend " + backend.getName(), e); 2146 } 2147 } 2148 vdb.releaseReadLockBackendLists(); 2149 } 2150 2151 2161 public void enableBackend(DatabaseBackend db, boolean writeEnabled) 2162 throws SQLException 2163 { 2164 logger.info(Translate.get("loadbalancer.backend.enabling", db.getName())); 2165 if (!db.isInitialized()) 2166 db.initializeConnections(); 2167 db.enableRead(); 2168 if (writeEnabled) 2169 db.enableWrite(); 2170 numberOfEnabledBackends++; 2171 } 2172 2173 2183 public void disableBackend(DatabaseBackend db, boolean forceDisable) 2184 throws SQLException 2185 { 2186 logger.info(Translate.get("loadbalancer.backend.disabling", db.getName())); 2187 numberOfEnabledBackends--; 2188 db.disable(); 2189 if (db.isInitialized()) 2190 db.finalizeConnections(); 2191 } 2192 2193 2196 public int getNumberOfEnabledBackends() 2197 { 2198 return numberOfEnabledBackends; 2199 } 2200 2201 2205 2208 public String getXmlImpl() 2209 { 2210 StringBuffer info = new StringBuffer (); 2211 info.append("<" + DatabasesXmlTags.ELT_ParallelDB + ">"); 2212 info.append(getParallelDBXml()); 2213 info.append("</" + DatabasesXmlTags.ELT_ParallelDB + ">"); 2214 return info.toString(); 2215 } 2216 2217 2222 public abstract String getParallelDBXml(); 2223 2224} | Popular Tags |