1 23 24 package org.continuent.sequoia.controller.loadbalancer.singledb; 25 26 import java.sql.Connection ; 27 import java.sql.SQLException ; 28 import java.sql.Savepoint ; 29 30 import org.continuent.sequoia.common.exceptions.BadConnectionException; 31 import org.continuent.sequoia.common.exceptions.NoMoreBackendException; 32 import org.continuent.sequoia.common.exceptions.UnreachableBackendException; 33 import org.continuent.sequoia.common.i18n.Translate; 34 import org.continuent.sequoia.common.log.Trace; 35 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 36 import org.continuent.sequoia.controller.backend.DatabaseBackend; 37 import org.continuent.sequoia.controller.backend.result.ControllerResultSet; 38 import org.continuent.sequoia.controller.backend.result.ExecuteResult; 39 import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult; 40 import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult; 41 import org.continuent.sequoia.controller.cache.metadata.MetadataCache; 42 import org.continuent.sequoia.controller.connection.AbstractConnectionManager; 43 import org.continuent.sequoia.controller.connection.PooledConnection; 44 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer; 45 import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException; 46 import org.continuent.sequoia.controller.loadbalancer.policies.WaitForCompletionPolicy; 47 import org.continuent.sequoia.controller.requestmanager.RAIDbLevels; 48 import org.continuent.sequoia.controller.requestmanager.TransactionMetaData; 49 import org.continuent.sequoia.controller.requests.AbstractRequest; 50 import org.continuent.sequoia.controller.requests.AbstractWriteRequest; 51 import org.continuent.sequoia.controller.requests.ParsingGranularities; 52 import org.continuent.sequoia.controller.requests.SelectRequest; 53 import org.continuent.sequoia.controller.requests.StoredProcedure; 54 import org.continuent.sequoia.controller.requests.UnknownReadRequest; 55 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase; 56 57 72 public class SingleDB extends AbstractLoadBalancer 73 { 74 84 private DatabaseBackend backend; 85 86 private static Trace logger = Trace 87 .getLogger("org.continuent.sequoia.controller.loadbalancer.SingleDB"); 88 89 static Trace endUserLogger = Trace 90 .getLogger("org.continuent.sequoia.enduser"); 91 92 95 96 103 public SingleDB(VirtualDatabase vdb) throws Exception 104 { 105 super(vdb, RAIDbLevels.SingleDB, ParsingGranularities.NO_PARSING); 107 this.waitForCompletionPolicy = new WaitForCompletionPolicy( 108 WaitForCompletionPolicy.ALL, false, ParsingGranularities.NO_PARSING); 109 } 110 111 114 115 124 public ControllerResultSet statementExecuteQuery(SelectRequest request, 125 MetadataCache metadataCache) throws SQLException 126 { 127 if (backend == null) 128 throw new NoMoreBackendException(Translate.get( 129 "loadbalancer.execute.no.backend.available", request.getId())); 130 131 try 132 { 133 AbstractConnectionManager cm = backend.getConnectionManager(request 134 .getLogin()); 135 if (request.isAutoCommit()) 136 { 137 ControllerResultSet rs = null; 138 boolean badConnection; 139 do 140 { 141 badConnection = false; 142 PooledConnection c = null; 144 try 145 { 146 c = cm.retrieveConnectionInAutoCommit(request); 147 } 148 catch (UnreachableBackendException e1) 149 { 150 String backendName = backend.getName(); 151 String msg = Translate.get( 152 "loadbalancer.backend.disabling.unreachable", backendName); 153 logger.error(msg); 154 endUserLogger.error(msg); 155 disableBackend(backend, true); 156 backend = null; 157 throw new SQLException (Translate.get( 158 "loadbalancer.backend.unreacheable", backendName)); 159 } 160 161 if (c == null) 163 throw new SQLException (Translate.get( 164 "loadbalancer.backend.no.connection", backend.getName())); 165 166 try 168 { 169 rs = executeStatementExecuteQueryOnBackend(request, backend, null, 170 c.getConnection(), metadataCache); 171 cm.releaseConnectionInAutoCommit(request, c); 172 } 173 catch (SQLException e) 174 { 175 cm.releaseConnectionInAutoCommit(request, c); 176 throw new SQLException (Translate.get( 177 "loadbalancer.request.failed.on.backend", new String []{ 178 request.getSqlShortForm(vdb.getSqlShortFormLength()), 179 backend.getName(), e.getMessage()})); 180 } 181 catch (BadConnectionException e) 182 { cm.deleteConnection(c); 184 badConnection = true; 185 } 186 catch (Throwable e) 187 { 188 cm.releaseConnectionInAutoCommit(request, c); 189 throw new SQLException (Translate.get( 190 "loadbalancer.request.failed.on.backend", new String []{ 191 request.getSqlShortForm(vdb.getSqlShortFormLength()), 192 backend.getName(), e.getMessage()})); 193 } 194 } 195 while (badConnection); 196 return rs; 197 } 198 else 199 { 200 long tid = request.getTransactionId(); 201 PooledConnection c = cm.retrieveConnectionForTransaction(tid); 203 204 if (c == null) 206 throw new SQLException (Translate.get( 207 "loadbalancer.unable.retrieve.connection", new String []{ 208 String.valueOf(tid), backend.getName()})); 209 210 ControllerResultSet rs = null; 212 try 213 { 214 rs = executeStatementExecuteQueryOnBackend(request, backend, null, c 215 .getConnection(), metadataCache); 216 } 217 catch (SQLException e) 218 { 219 throw new SQLException (Translate.get( 220 "loadbalancer.request.failed.on.backend", new String []{ 221 request.getSqlShortForm(vdb.getSqlShortFormLength()), 222 backend.getName(), e.getMessage()})); 223 } 224 catch (BadConnectionException e) 225 { cm.deleteConnection(tid); 227 throw new SQLException (Translate.get( 228 "loadbalancer.connection.failed", new String []{ 229 String.valueOf(tid), backend.getName(), e.getMessage()})); 230 } 231 catch (Throwable e) 232 { 233 throw new SQLException (Translate.get( 234 "loadbalancer.request.failed.on.backend", new String []{ 235 request.getSqlShortForm(vdb.getSqlShortFormLength()), 236 backend.getName(), e.getMessage()})); 237 } 238 return rs; 239 } 240 } 241 catch (RuntimeException e) 242 { 243 String msg = "Request '" 244 + request.getSqlShortForm(vdb.getSqlShortFormLength()) 245 + "' failed on backend " + backend.getURL() + " (" + e + ")"; 246 logger.fatal(msg, e); 247 throw new SQLException (msg); 248 } 249 } 250 251 258 public ExecuteUpdateResult statementExecuteUpdate(AbstractWriteRequest request) 259 throws SQLException 260 { 261 if (backend == null) 262 throw new NoMoreBackendException(Translate.get( 263 "loadbalancer.execute.no.backend.available", request.getId())); 264 265 try 266 { 267 AbstractConnectionManager cm = backend.getConnectionManager(request 268 .getLogin()); 269 if (request.isAutoCommit()) 270 { 271 if (!backend.canAcceptTasks(request)) 274 throw new SQLException (Translate.get( 275 "loadbalancer.backend.is.disabling", new String []{ 276 request.getSqlShortForm(vdb.getSqlShortFormLength()), 277 backend.getName()})); 278 279 PooledConnection c = null; 281 try 282 { 283 c = cm.retrieveConnectionInAutoCommit(request); 284 } 285 catch (UnreachableBackendException e1) 286 { 287 String backendName = backend.getName(); 288 String msg = Translate.get( 289 "loadbalancer.backend.disabling.unreachable", backendName); 290 logger.error(msg); 291 endUserLogger.error(msg); 292 disableBackend(backend, true); 293 backend = null; 294 throw new SQLException (Translate.get( 295 "loadbalancer.backend.unreacheable", backendName)); 296 } 297 298 if (c == null) 300 throw new SQLException (Translate.get( 301 "loadbalancer.backend.no.connection", backend.getName())); 302 303 ExecuteUpdateResult result; 305 try 306 { 307 result = executeStatementExecuteUpdateOnBackend(request, backend, 308 null, c.getConnection()); 309 } 310 catch (Exception e) 311 { 312 throw new SQLException (Translate.get( 313 "loadbalancer.request.failed.on.backend", new String []{ 314 request.getSqlShortForm(vdb.getSqlShortFormLength()), 315 backend.getName(), e.getMessage()})); 316 } 317 finally 318 { 319 cm.releaseConnectionInAutoCommit(request, c); 320 } 321 return result; 322 } 323 else 324 { PooledConnection c = cm.retrieveConnectionForTransaction(request 326 .getTransactionId()); 327 328 if (c == null) 330 throw new SQLException (Translate.get( 331 "loadbalancer.unable.retrieve.connection", 332 new String []{String.valueOf(request.getTransactionId()), 333 backend.getName()})); 334 335 try 337 { 338 ExecuteUpdateResult result = executeStatementExecuteUpdateOnBackend( 339 request, backend, null, c.getConnection()); 340 return result; 341 } 342 catch (Exception e) 343 { 344 throw new SQLException (Translate.get( 345 "loadbalancer.request.failed.on.backend", new String []{ 346 request.getSqlShortForm(vdb.getSqlShortFormLength()), 347 backend.getName(), e.getMessage()})); 348 } 349 } 350 } 351 catch (RuntimeException e) 352 { 353 String msg = Translate.get("loadbalancer.request.failed.on.backend", 354 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 355 backend.getName(), e.getMessage()}); 356 endUserLogger.fatal(msg); 357 logger.fatal(msg, e); 358 throw new SQLException (msg); 359 } 360 } 361 362 366 public GeneratedKeysResult statementExecuteUpdateWithKeys( 367 AbstractWriteRequest request, MetadataCache metadataCache) 368 throws SQLException 369 { 370 if (backend == null) 371 throw new NoMoreBackendException(Translate.get( 372 "loadbalancer.execute.no.backend.available", request.getId())); 373 374 if (!backend.getDriverCompliance().supportGetGeneratedKeys()) 375 throw new SQLException (Translate.get( 376 "loadbalancer.backend.autogeneratedkeys.unsupported", backend 377 .getName())); 378 379 try 380 { 381 AbstractConnectionManager cm = backend.getConnectionManager(request 382 .getLogin()); 383 if (request.isAutoCommit()) 384 { 385 if (!backend.canAcceptTasks(request)) 388 throw new SQLException (Translate.get( 389 "loadbalancer.backend.is.disabling", new String []{ 390 request.getSqlShortForm(vdb.getSqlShortFormLength()), 391 backend.getName()})); 392 393 PooledConnection c = null; 395 try 396 { 397 c = cm.retrieveConnectionInAutoCommit(request); 398 } 399 catch (UnreachableBackendException e1) 400 { 401 String backendName = backend.getName(); 402 String msg = Translate.get( 403 "loadbalancer.backend.disabling.unreachable", backendName); 404 logger.error(msg); 405 endUserLogger.error(msg); 406 disableBackend(backend, true); 407 backend = null; 408 throw new SQLException (Translate.get( 409 "loadbalancer.backend.unreacheable", backendName)); 410 } 411 412 if (c == null) 414 throw new SQLException (Translate.get( 415 "loadbalancer.backend.no.connection", backend.getName())); 416 417 GeneratedKeysResult result; 419 try 420 { 421 result = executeStatementExecuteUpdateWithKeysOnBackend(request, 422 backend, null, c.getConnection(), metadataCache); 423 } 424 catch (Exception e) 425 { 426 throw new SQLException (Translate.get( 427 "loadbalancer.request.failed.on.backend", new String []{ 428 request.getSqlShortForm(vdb.getSqlShortFormLength()), 429 backend.getName(), e.getMessage()})); 430 } 431 finally 432 { 433 cm.releaseConnectionInAutoCommit(request, c); 434 } 435 return result; 436 } 437 else 438 { 439 PooledConnection c = cm.retrieveConnectionForTransaction(request 441 .getTransactionId()); 442 443 if (c == null) 445 throw new SQLException (Translate.get( 446 "loadbalancer.unable.retrieve.connection", 447 new String []{String.valueOf(request.getTransactionId()), 448 backend.getName()})); 449 450 try 452 { 453 GeneratedKeysResult result = executeStatementExecuteUpdateWithKeysOnBackend( 454 request, backend, null, c.getConnection(), metadataCache); 455 return result; 456 } 457 catch (Exception e) 458 { 459 throw new SQLException (Translate.get( 460 "loadbalancer.request.failed.on.backend", new String []{ 461 request.getSqlShortForm(vdb.getSqlShortFormLength()), 462 backend.getName(), e.getMessage()})); 463 } 464 finally 465 { 466 backend.removePendingRequest(request); 467 } 468 } 469 } 470 catch (RuntimeException e) 471 { 472 String msg = Translate.get("loadbalancer.request.failed.on.backend", 473 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 474 backend.getName(), e.getMessage()}); 475 logger.fatal(msg, e); 476 endUserLogger.fatal(msg); 477 throw new SQLException (msg); 478 } 479 } 480 481 485 public ExecuteResult statementExecute(AbstractRequest request, 486 MetadataCache metadataCache) throws SQLException 487 { 488 if (backend == null) 489 throw new SQLException ("No available backend to execute request " 490 + request.getId()); 491 492 try 493 { 494 AbstractConnectionManager cm = backend.getConnectionManager(request 495 .getLogin()); 496 if (request.isAutoCommit()) 497 { PooledConnection c = null; 499 try 500 { 501 c = cm.retrieveConnectionInAutoCommit(request); 502 } 503 catch (UnreachableBackendException e1) 504 { 505 String backendName = backend.getName(); 506 String msg = Translate.get( 507 "loadbalancer.backend.disabling.unreachable", backendName); 508 logger.error(msg); 509 endUserLogger.error(msg); 510 disableBackend(backend, true); 511 backend = null; 512 throw new SQLException (Translate.get( 513 "loadbalancer.backend.unreacheable", backendName)); 514 } 515 516 if (c == null) 518 throw new SQLException (Translate.get( 519 "loadbalancer.backend.no.connection", backend.getName())); 520 521 ExecuteResult rs = null; 523 try 524 { 525 rs = AbstractLoadBalancer.executeStatementExecuteOnBackend(request, 526 backend, null, c.getConnection(), metadataCache); 527 } 528 catch (Exception e) 529 { 530 throw new SQLException (Translate.get( 531 "loadbalancer.request.failed.on.backend", new String []{ 532 request.getSqlShortForm(vdb.getSqlShortFormLength()), 533 backend.getName(), e.getMessage()})); 534 } 535 finally 536 { 537 cm.releaseConnectionInAutoCommit(request, c); 538 } 539 return rs; 540 } 541 else 542 { PooledConnection c = cm.retrieveConnectionForTransaction(request 544 .getTransactionId()); 545 546 if (c == null) 548 throw new SQLException (Translate.get( 549 "loadbalancer.unable.retrieve.connection", 550 new String []{String.valueOf(request.getTransactionId()), 551 backend.getName()})); 552 553 try 555 { 556 return AbstractLoadBalancer.executeStatementExecuteOnBackend(request, 557 backend, null, c.getConnection(), metadataCache); 558 } 559 catch (Exception e) 560 { 561 throw new SQLException (Translate.get( 562 "loadbalancer.request.failed.on.backend", new String []{ 563 request.getSqlShortForm(vdb.getSqlShortFormLength()), 564 backend.getName(), e.getMessage()})); 565 } 566 } 567 } 568 catch (RuntimeException e) 569 { 570 String msg = Translate.get("loadbalancer.request.failed.on.backend", 571 new String []{request.getSqlShortForm(vdb.getSqlShortFormLength()), 572 backend.getName(), e.getMessage()}); 573 logger.fatal(msg, e); 574 endUserLogger.fatal(msg); 575 throw new SQLException (msg); 576 } 577 } 578 579 583 public ControllerResultSet readOnlyCallableStatementExecuteQuery( 584 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 585 { 586 return callableStatementExecuteQuery(proc, metadataCache); 587 } 588 589 593 public ExecuteResult readOnlyCallableStatementExecute(StoredProcedure proc, 594 MetadataCache metadataCache) throws SQLException 595 { 596 return callableStatementExecute(proc, metadataCache); 597 } 598 599 603 public ControllerResultSet callableStatementExecuteQuery( 604 StoredProcedure proc, MetadataCache metadataCache) throws SQLException 605 { 606 if (backend == null) 607 throw new SQLException ( 608 "No available backend to execute stored procedure " + proc.getId()); 609 610 try 611 { 612 AbstractConnectionManager cm = backend.getConnectionManager(proc 613 .getLogin()); 614 if (proc.isAutoCommit()) 615 { PooledConnection c = null; 617 try 618 { 619 c = cm.retrieveConnectionInAutoCommit(proc); 620 } 621 catch (UnreachableBackendException e1) 622 { 623 String backendName = backend.getName(); 624 String msg = Translate.get( 625 "loadbalancer.backend.disabling.unreachable", backendName); 626 logger.error(msg); 627 endUserLogger.error(msg); 628 disableBackend(backend, true); 629 backend = null; 630 throw new SQLException (Translate.get( 631 "loadbalancer.backend.unreacheable", backendName)); 632 } 633 634 if (c == null) 636 throw new SQLException (Translate.get( 637 "loadbalancer.backend.no.connection", backend.getName())); 638 639 ControllerResultSet rs = null; 641 try 642 { 643 rs = AbstractLoadBalancer 644 .executeCallableStatementExecuteQueryOnBackend(proc, backend, 645 null, c.getConnection(), metadataCache); 646 } 647 catch (Exception e) 648 { 649 throw new SQLException (Translate.get( 650 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 651 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 652 backend.getName(), e.getMessage()})); 653 } 654 finally 655 { 656 cm.releaseConnectionInAutoCommit(proc, c); 657 } 658 return rs; 659 } 660 else 661 { PooledConnection c = cm.retrieveConnectionForTransaction(proc 663 .getTransactionId()); 664 665 if (c == null) 667 throw new SQLException (Translate.get( 668 "loadbalancer.unable.retrieve.connection", new String []{ 669 String.valueOf(proc.getTransactionId()), backend.getName()})); 670 671 try 673 { 674 ControllerResultSet result = AbstractLoadBalancer 675 .executeCallableStatementExecuteQueryOnBackend(proc, backend, 676 null, c.getConnection(), metadataCache); 677 return result; 678 } 679 catch (Exception e) 680 { 681 throw new SQLException (Translate.get( 682 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 683 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 684 backend.getName(), e.getMessage()})); 685 } 686 } 687 } 688 catch (RuntimeException e) 689 { 690 String msg = Translate.get( 691 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 692 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 693 backend.getName(), e.getMessage()}); 694 logger.fatal(msg, e); 695 endUserLogger.fatal(msg); 696 throw new SQLException (msg); 697 } 698 } 699 700 703 public ExecuteUpdateResult callableStatementExecuteUpdate(StoredProcedure proc) 704 throws SQLException 705 { 706 if (backend == null) 707 throw new SQLException ( 708 "No available backend to execute stored procedure " + proc.getId()); 709 710 try 711 { 712 AbstractConnectionManager cm = backend.getConnectionManager(proc 713 .getLogin()); 714 if (proc.isAutoCommit()) 715 { PooledConnection c = null; 717 try 718 { 719 c = cm.retrieveConnectionInAutoCommit(proc); 720 } 721 catch (UnreachableBackendException e1) 722 { 723 String backendName = backend.getName(); 724 String msg = Translate.get( 725 "loadbalancer.backend.disabling.unreachable", backendName); 726 logger.error(msg); 727 endUserLogger.error(msg); 728 disableBackend(backend, true); 729 backend = null; 730 throw new SQLException (Translate.get( 731 "loadbalancer.backend.unreacheable", backendName)); 732 } 733 734 if (c == null) 736 throw new SQLException (Translate.get( 737 "loadbalancer.backend.no.connection", backend.getName())); 738 739 ExecuteUpdateResult result; 741 try 742 { 743 result = AbstractLoadBalancer 744 .executeCallableStatementExecuteUpdateOnBackend(proc, backend, 745 null, c.getConnection()); 746 } 747 catch (Exception e) 748 { 749 throw new SQLException (Translate.get( 750 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 751 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 752 backend.getName(), e.getMessage()})); 753 } 754 finally 755 { 756 cm.releaseConnectionInAutoCommit(proc, c); 757 } 758 return result; 759 } 760 else 761 { PooledConnection c = cm.retrieveConnectionForTransaction(proc 763 .getTransactionId()); 764 765 if (c == null) 767 throw new SQLException (Translate.get( 768 "loadbalancer.unable.retrieve.connection", new String []{ 769 String.valueOf(proc.getTransactionId()), backend.getName()})); 770 771 try 773 { 774 ExecuteUpdateResult result = AbstractLoadBalancer 775 .executeCallableStatementExecuteUpdateOnBackend(proc, backend, 776 null, c.getConnection()); 777 return result; 778 } 779 catch (Exception e) 780 { 781 throw new SQLException (Translate.get( 782 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 783 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 784 backend.getName(), e.getMessage()})); 785 } 786 } 787 } 788 catch (RuntimeException e) 789 { 790 String msg = Translate.get( 791 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 792 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 793 backend.getName(), e.getMessage()}); 794 logger.fatal(msg, e); 795 endUserLogger.fatal(msg); 796 throw new SQLException (msg); 797 } 798 } 799 800 804 public ExecuteResult callableStatementExecute(StoredProcedure proc, 805 MetadataCache metadataCache) throws SQLException 806 { 807 if (backend == null) 808 throw new SQLException ( 809 "No available backend to execute stored procedure " + proc.getId()); 810 811 try 812 { 813 AbstractConnectionManager cm = backend.getConnectionManager(proc 814 .getLogin()); 815 if (proc.isAutoCommit()) 816 { PooledConnection c = null; 818 try 819 { 820 c = cm.retrieveConnectionInAutoCommit(proc); 821 } 822 catch (UnreachableBackendException e1) 823 { 824 String backendName = backend.getName(); 825 String msg = Translate.get( 826 "loadbalancer.backend.disabling.unreachable", backendName); 827 logger.error(msg); 828 endUserLogger.error(msg); 829 disableBackend(backend, true); 830 backend = null; 831 throw new SQLException (Translate.get( 832 "loadbalancer.backend.unreacheable", backendName)); 833 } 834 835 if (c == null) 837 throw new SQLException (Translate.get( 838 "loadbalancer.backend.no.connection", backend.getName())); 839 840 ExecuteResult rs = null; 842 try 843 { 844 rs = AbstractLoadBalancer.executeCallableStatementExecuteOnBackend( 845 proc, backend, null, c.getConnection(), metadataCache); 846 } 847 catch (Exception e) 848 { 849 throw new SQLException (Translate.get( 850 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 851 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 852 backend.getName(), e.getMessage()})); 853 } 854 finally 855 { 856 cm.releaseConnectionInAutoCommit(proc, c); 857 } 858 return rs; 859 } 860 else 861 { PooledConnection c = cm.retrieveConnectionForTransaction(proc 863 .getTransactionId()); 864 865 if (c == null) 867 throw new SQLException (Translate.get( 868 "loadbalancer.unable.retrieve.connection", new String []{ 869 String.valueOf(proc.getTransactionId()), backend.getName()})); 870 871 try 873 { 874 ExecuteResult result = AbstractLoadBalancer 875 .executeCallableStatementExecuteOnBackend(proc, backend, null, c 876 .getConnection(), metadataCache); 877 return result; 878 } 879 catch (Exception e) 880 { 881 throw new SQLException (Translate.get( 882 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 883 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 884 backend.getName(), e.getMessage()})); 885 } 886 } 887 } 888 catch (RuntimeException e) 889 { 890 String msg = Translate.get( 891 "loadbalancer.storedprocedure.failed.on.backend", new String []{ 892 proc.getSqlShortForm(vdb.getSqlShortFormLength()), 893 backend.getName(), e.getMessage()}); 894 logger.fatal(msg, e); 895 endUserLogger.fatal(msg); 896 throw new SQLException (msg); 897 } 898 } 899 900 903 public ControllerResultSet getPreparedStatementGetMetaData( 904 AbstractRequest request) throws SQLException 905 { 906 if (backend == null) 907 throw new NoMoreBackendException(Translate.get( 908 "loadbalancer.execute.no.backend.available", request 909 .getSqlOrTemplate())); 910 911 try 912 { 913 AbstractConnectionManager cm = backend.getConnectionManager(request 914 .getLogin()); 915 ControllerResultSet rs = null; 916 boolean badConnection; 917 do 918 { 919 badConnection = false; 920 PooledConnection c = null; 922 try 923 { 924 c = cm.retrieveConnectionInAutoCommit(request); 925 } 926 catch (UnreachableBackendException e1) 927 { 928 String backendName = backend.getName(); 929 String msg = Translate.get( 930 "loadbalancer.backend.disabling.unreachable", backendName); 931 logger.error(msg); 932 endUserLogger.error(msg); 933 disableBackend(backend, true); 934 backend = null; 935 throw new SQLException (Translate.get( 936 "loadbalancer.backend.unreacheable", backendName)); 937 } 938 939 if (c == null) 941 throw new SQLException (Translate.get( 942 "loadbalancer.backend.no.connection", backend.getName())); 943 944 try 946 { 947 rs = preparedStatementGetMetaDataOnBackend( 948 request.getSqlOrTemplate(), backend, c.getConnection()); 949 cm.releaseConnectionInAutoCommit(request, c); 950 } 951 catch (SQLException e) 952 { 953 cm.releaseConnectionInAutoCommit(request, c); 954 throw new SQLException (Translate.get( 955 "loadbalancer.request.failed.on.backend", 956 new String []{request.getSqlOrTemplate(), backend.getName(), 957 e.getMessage()})); 958 } 959 catch (BadConnectionException e) 960 { cm.deleteConnection(c); 962 badConnection = true; 963 } 964 catch (Throwable e) 965 { 966 cm.releaseConnectionInAutoCommit(request, c); 967 throw new SQLException (Translate.get( 968 "loadbalancer.request.failed.on.backend", 969 new String []{request.getSqlOrTemplate(), backend.getName(), 970 e.getMessage()})); 971 } 972 } 973 while (badConnection); 974 return rs; 975 } 976 catch (RuntimeException e) 977 { 978 String msg = Translate.get("loadbalancer.getmetadata.failed", 979 new String []{request.getSqlOrTemplate(), backend.getURL(), 980 e.getMessage()}); 981 logger.fatal(msg, e); 982 endUserLogger.fatal(msg); 983 throw new SQLException (msg); 984 } 985 } 986 987 990 991 994 public void abort(TransactionMetaData tm) throws SQLException 995 { 996 rollback(tm); 997 } 998 999 1005 public void begin(TransactionMetaData tm) throws SQLException 1006 { 1007 if (backend == null) 1008 throw new SQLException ("No available backend to begin transaction " 1009 + tm.getTransactionId()); 1010 1011 if (!backend.canAcceptTasks(null)) 1013 throw new SQLException (Translate.get("loadbalancer.backend.is.disabling", 1014 new String []{"begin transaction " + tm.getTransactionId(), 1015 backend.getName()})); 1016 1017 try 1018 { 1019 PooledConnection c = backend.getConnectionManager(tm.getLogin()) 1020 .getConnectionForTransaction(tm.getTransactionId()); 1021 1022 if (c == null) 1023 throw new SQLException (Translate.get( 1024 "loadbalancer.backend.no.connection", backend.getName())); 1025 1026 c.getConnection().setAutoCommit(false); 1027 } 1028 catch (Exception e) 1029 { 1030 throw new SQLException ("Begin of transaction " + tm.getTransactionId() 1031 + " failed on backend " + backend.getURL() + " (" + e + ")"); 1032 } 1033 } 1034 1035 1041 public void commit(TransactionMetaData tm) throws SQLException 1042 { 1043 if (backend == null) 1044 throw new SQLException ("No available backend to commit transaction " 1045 + tm.getTransactionId()); 1046 1047 try 1048 { 1049 AbstractConnectionManager cm = backend 1050 .getConnectionManager(tm.getLogin()); 1051 PooledConnection pc = cm.retrieveConnectionForTransaction(tm 1052 .getTransactionId()); 1053 1054 if (pc == null) 1055 throw new SQLException ("No connection found for transaction " 1056 + tm.getTransactionId()); 1057 1058 try 1059 { 1060 Connection c = pc.getConnection(); 1061 c.commit(); 1062 c.setAutoCommit(true); 1063 } 1064 catch (SQLException e) 1065 { 1066 throw new SQLException (Translate.get("loadbalancer.commit.failed", 1067 new String []{String.valueOf(tm.getTransactionId()), 1068 backend.getName(), e.getMessage()})); 1069 } 1070 finally 1071 { 1072 cm.releaseConnectionForTransaction(tm.getTransactionId()); 1073 } 1074 } 1075 catch (RuntimeException e) 1076 { 1077 String msg = Translate.get("loadbalancer.commit.failed", new String []{ 1078 String.valueOf(tm.getTransactionId()), backend.getName(), 1079 e.getMessage()}); 1080 logger.fatal(msg, e); 1081 endUserLogger.fatal(msg); 1082 throw new SQLException (msg); 1083 } 1084 } 1085 1086 1092 public void rollback(TransactionMetaData tm) throws SQLException 1093 { 1094 if (backend == null) 1095 throw new SQLException ("No available backend to rollback transaction " 1096 + tm.getTransactionId()); 1097 1098 try 1099 { 1100 AbstractConnectionManager cm = backend 1101 .getConnectionManager(tm.getLogin()); 1102 PooledConnection pc = cm.retrieveConnectionForTransaction(tm 1103 .getTransactionId()); 1104 1105 if (pc == null) 1106 throw new SQLException ("No connection found for transaction " 1107 + tm.getTransactionId()); 1108 1109 try 1110 { 1111 Connection c = pc.getConnection(); 1112 c.rollback(); 1113 c.setAutoCommit(true); 1114 } 1115 catch (SQLException e) 1116 { 1117 throw new SQLException (Translate.get("loadbalancer.rollback.failed", 1118 new String []{String.valueOf(tm.getTransactionId()), 1119 backend.getName(), e.getMessage()})); 1120 } 1121 finally 1122 { 1123 cm.releaseConnectionForTransaction(tm.getTransactionId()); 1124 } 1125 } 1126 catch (RuntimeException e) 1127 { 1128 String msg = Translate.get("loadbalancer.rollback.failed", new String []{ 1129 String.valueOf(tm.getTransactionId()), backend.getName(), 1130 e.getMessage()}); 1131 logger.fatal(msg, e); 1132 endUserLogger.fatal(msg); 1133 throw new SQLException (msg); 1134 } 1135 } 1136 1137 1144 public void rollbackToSavepoint(TransactionMetaData tm, String savepointName) 1145 throws SQLException 1146 { 1147 if (backend == null) 1148 throw new SQLException ("No available backend to rollback transaction " 1149 + tm.getTransactionId()); 1150 1151 try 1152 { 1153 AbstractConnectionManager cm = backend 1154 .getConnectionManager(tm.getLogin()); 1155 PooledConnection c = cm.retrieveConnectionForTransaction(tm 1156 .getTransactionId()); 1157 1158 if (c == null) 1159 throw new SQLException ("No connection found for transaction " 1160 + tm.getTransactionId()); 1161 1162 Savepoint savepoint = backend.getSavepoint( 1163 new Long (tm.getTransactionId()), savepointName); 1164 1165 if (savepoint == null) 1166 throw new SQLException ("No savepoint with name " + savepointName 1167 + " has been found for transaction " + tm.getTransactionId()); 1168 1169 try 1170 { 1171 c.getConnection().rollback(savepoint); 1172 } 1173 catch (SQLException e) 1174 { 1175 throw new SQLException (Translate.get( 1176 "loadbalancer.rollbacksavepoint.failed", new String []{ 1177 savepointName, String.valueOf(tm.getTransactionId()), 1178 backend.getName(), e.getMessage()})); 1179 } 1180 } 1181 catch (RuntimeException e) 1182 { 1183 String msg = Translate.get("loadbalancer.rollbacksavepoint.failed", 1184 new String []{savepointName, String.valueOf(tm.getTransactionId()), 1185 backend.getName(), e.getMessage()}); 1186 logger.fatal(msg, e); 1187 endUserLogger.fatal(msg); 1188 throw new SQLException (msg); 1189 } 1190 } 1191 1192 1199 public void releaseSavepoint(TransactionMetaData tm, String savepointName) 1200 throws SQLException 1201 { 1202 if (backend == null) 1203 throw new SQLException ("No available backend to release savepoint from " 1204 + " transaction " + tm.getTransactionId()); 1205 1206 try 1207 { 1208 AbstractConnectionManager cm = backend 1209 .getConnectionManager(tm.getLogin()); 1210 PooledConnection c = cm.retrieveConnectionForTransaction(tm 1211 .getTransactionId()); 1212 1213 if (c == null) 1214 throw new SQLException ("No connection found for transaction " 1215 + tm.getTransactionId()); 1216 1217 Savepoint savepoint = backend.getSavepoint( 1218 new Long (tm.getTransactionId()), savepointName); 1219 1220 if (savepoint == null) 1221 throw new SQLException ("No savepoint with name " + savepointName 1222 + " has been " + "found for transaction " + tm.getTransactionId()); 1223 1224 try 1225 { 1226 c.getConnection().releaseSavepoint(savepoint); 1227 } 1228 catch (SQLException e) 1229 { 1230 throw new SQLException (Translate.get( 1231 "loadbalancer.releasesavepoint.failed", new String []{savepointName, 1232 String.valueOf(tm.getTransactionId()), backend.getName(), 1233 e.getMessage()})); 1234 } 1235 finally 1236 { 1237 backend.removeSavepoint(new Long (tm.getTransactionId()), savepoint); 1238 } 1239 } 1240 catch (RuntimeException e) 1241 { 1242 String msg = Translate.get("loadbalancer.releasesavepoint.failed", 1243 new String []{savepointName, String.valueOf(tm.getTransactionId()), 1244 backend.getName(), e.getMessage()}); 1245 logger.fatal(msg, e); 1246 endUserLogger.fatal(msg); 1247 throw new SQLException (msg); 1248 } 1249 } 1250 1251 1260 public void setSavepoint(TransactionMetaData tm, String savepointName) 1261 throws AllBackendsFailedException, SQLException 1262 { 1263 if (backend == null) 1264 throw new SQLException ("No available backend to set savepoint to " 1265 + " transaction " + tm.getTransactionId()); 1266 1267 try 1268 { 1269 AbstractConnectionManager cm = backend 1270 .getConnectionManager(tm.getLogin()); 1271 PooledConnection c = cm.retrieveConnectionForTransaction(tm 1272 .getTransactionId()); 1273 1274 if (c == null) 1275 throw new SQLException ("No connection found for transaction " 1276 + tm.getTransactionId()); 1277 1278 Savepoint savepoint = null; 1279 try 1280 { 1281 savepoint = c.getConnection().setSavepoint(savepointName); 1282 } 1283 catch (SQLException e) 1284 { 1285 throw new SQLException (Translate.get( 1286 "loadbalancer.setsavepoint.failed", new String []{savepointName, 1287 String.valueOf(tm.getTransactionId()), backend.getName(), 1288 e.getMessage()})); 1289 } 1290 finally 1291 { 1292 if (savepoint != null) 1293 backend.addSavepoint(new Long (tm.getTransactionId()), savepoint); 1294 } 1295 } 1296 catch (RuntimeException e) 1297 { 1298 String msg = Translate.get("loadbalancer.setsavepoint.failed", 1299 new String []{savepointName, String.valueOf(tm.getTransactionId()), 1300 backend.getName(), e.getMessage()}); 1301 logger.fatal(msg, e); 1302 endUserLogger.fatal(msg); 1303 throw new SQLException (msg); 1304 } 1305 } 1306 1307 1311 public void closePersistentConnection(String login, 1312 long persistentConnectionId) throws SQLException 1313 { 1314 AbstractConnectionManager cm = backend.getConnectionManager(login); 1315 if (cm != null) 1316 { 1317 cm.releasePersistentConnectionInAutoCommit(persistentConnectionId); 1319 backend.removePersistentConnection(persistentConnectionId); 1320 } 1321 } 1322 1323 1327 public void openPersistentConnection(String login, long persistentConnectionId) 1328 throws SQLException 1329 { 1330 AbstractConnectionManager cm = backend.getConnectionManager(login); 1331 if (cm == null) 1332 { 1333 throw new SQLException ("No connection manager found for user " + login); 1334 } 1335 1336 AbstractRequest request = new UnknownReadRequest("", false, 0, ""); 1338 request.setLogin(login); 1339 request.setPersistentConnection(true); 1340 request.setPersistentConnectionId(persistentConnectionId); 1341 try 1342 { 1343 PooledConnection c = cm.retrieveConnectionInAutoCommit(request); 1344 backend.addPersistentConnection(request.getPersistentConnectionId(), c); 1345 } 1346 catch (UnreachableBackendException e) 1347 { 1348 throw new SQLException ( 1349 "Backend is not reachable to open persistent conenction " 1350 + persistentConnectionId); 1351 } 1352 } 1353 1354 1357 1358 1366 public void enableBackend(DatabaseBackend db, boolean writeEnabled) 1367 throws SQLException 1368 { 1369 if (backend != null) 1370 { 1371 if (backend.isReadEnabled()) 1372 throw new SQLException ( 1373 "SingleDB load balancer accepts only one backend and " 1374 + backend.getName() + " is already enabled. Skipping " 1375 + db.getName() + " initialization."); 1376 } 1377 backend = db; 1378 logger.info(Translate.get("loadbalancer.backend.enabling", db.getName())); 1379 if (!backend.isInitialized()) 1380 backend.initializeConnections(); 1381 backend.enableRead(); 1382 if (writeEnabled) 1383 backend.enableWrite(); 1384 } 1385 1386 1394 public void disableBackend(DatabaseBackend db, boolean forceDisable) 1395 throws SQLException 1396 { 1397 if (backend.equals(db)) 1398 { 1399 logger 1400 .info(Translate.get("loadbalancer.backend.disabling", db.getName())); 1401 backend.disable(); 1402 if (backend.isInitialized()) 1403 backend.finalizeConnections(); 1404 backend = null; 1405 } 1406 else 1407 { 1408 String msg = "Trying to disable a non-existing backend " + db.getName(); 1409 logger.warn(msg); 1410 throw new SQLException (msg); 1411 } 1412 } 1413 1414 1418 public void setWeight(String name, int w) throws SQLException 1419 { 1420 throw new SQLException ("Weight is not supported with this load balancer"); 1421 } 1422 1423 1426 public int getNumberOfEnabledBackends() 1427 { 1428 if (backend == null) 1429 return 0; 1430 else 1431 return 1; 1432 } 1433 1434 1437 1438 1443 public String getInformation() 1444 { 1445 if (backend == null) 1446 return "SingleDB Request load balancer: !!!Warning!!! No enabled backend node found\n"; 1447 else 1448 return "SingleDB Request load balancer using " + backend.getURL() + "\n"; 1449 } 1450 1451 1454 public String getXmlImpl() 1455 { 1456 return "<" + DatabasesXmlTags.ELT_SingleDB + "/>"; 1457 } 1458 1459} | Popular Tags |