1 25 26 package org.continuent.sequoia.controller.requestmanager; 27 28 import java.sql.SQLException ; 29 import java.util.ArrayList ; 30 import java.util.Date ; 31 import java.util.Hashtable ; 32 import java.util.Iterator ; 33 import java.util.LinkedList ; 34 import java.util.List ; 35 import java.util.Vector ; 36 37 import javax.management.NotCompliantMBeanException ; 38 39 import org.continuent.sequoia.common.exceptions.BackupException; 40 import org.continuent.sequoia.common.exceptions.NoMoreBackendException; 41 import org.continuent.sequoia.common.exceptions.RollbackException; 42 import org.continuent.sequoia.common.exceptions.VirtualDatabaseException; 43 import org.continuent.sequoia.common.i18n.Translate; 44 import org.continuent.sequoia.common.jmx.JmxConstants; 45 import org.continuent.sequoia.common.jmx.management.BackendInfo; 46 import org.continuent.sequoia.common.jmx.management.BackendState; 47 import org.continuent.sequoia.common.jmx.management.DumpInfo; 48 import org.continuent.sequoia.common.jmx.mbeans.RequestManagerMBean; 49 import org.continuent.sequoia.common.jmx.notifications.SequoiaNotificationList; 50 import org.continuent.sequoia.common.log.Trace; 51 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 52 import org.continuent.sequoia.common.xml.XmlComponent; 53 import org.continuent.sequoia.controller.backend.BackendStateListener; 54 import org.continuent.sequoia.controller.backend.DatabaseBackend; 55 import org.continuent.sequoia.controller.backend.result.ControllerResultSet; 56 import org.continuent.sequoia.controller.backend.result.ExecuteResult; 57 import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult; 58 import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult; 59 import org.continuent.sequoia.controller.backup.BackupManager; 60 import org.continuent.sequoia.controller.backup.Backuper; 61 import org.continuent.sequoia.controller.cache.metadata.MetadataCache; 62 import org.continuent.sequoia.controller.cache.parsing.ParsingCache; 63 import org.continuent.sequoia.controller.cache.result.AbstractResultCache; 64 import org.continuent.sequoia.controller.cache.result.entries.AbstractResultCacheEntry; 65 import org.continuent.sequoia.controller.core.ControllerConstants; 66 import org.continuent.sequoia.controller.jmx.AbstractStandardMBean; 67 import org.continuent.sequoia.controller.jmx.MBeanServerManager; 68 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer; 69 import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException; 70 import org.continuent.sequoia.controller.loadbalancer.LoadBalancerControl; 71 import org.continuent.sequoia.controller.loadbalancer.policies.WaitForCompletionPolicy; 72 import org.continuent.sequoia.controller.recoverylog.BackendRecoveryInfo; 73 import org.continuent.sequoia.controller.recoverylog.RecoverThread; 74 import org.continuent.sequoia.controller.recoverylog.RecoveryLog; 75 import org.continuent.sequoia.controller.requests.AbstractRequest; 76 import org.continuent.sequoia.controller.requests.AbstractWriteRequest; 77 import org.continuent.sequoia.controller.requests.ParsingGranularities; 78 import org.continuent.sequoia.controller.requests.RequestFactory; 79 import org.continuent.sequoia.controller.requests.RequestType; 80 import org.continuent.sequoia.controller.requests.SelectRequest; 81 import org.continuent.sequoia.controller.requests.StoredProcedure; 82 import org.continuent.sequoia.controller.requests.UpdateRequest; 83 import org.continuent.sequoia.controller.scheduler.AbstractScheduler; 84 import org.continuent.sequoia.controller.semantic.SemanticBehavior; 85 import org.continuent.sequoia.controller.semantic.SemanticManager; 86 import org.continuent.sequoia.controller.sql.schema.DatabaseSchema; 87 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase; 88 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabaseWorkerThread; 89 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedCommit; 90 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedReleaseSavepoint; 91 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRollback; 92 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRollbackToSavepoint; 93 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedSetSavepoint; 94 95 109 public class RequestManager extends AbstractStandardMBean 110 implements 111 XmlComponent, 112 RequestManagerMBean 113 { 114 115 126 127 protected long beginTimeout; 128 129 130 protected long commitTimeout; 131 132 133 protected long rollbackTimeout; 134 135 136 protected VirtualDatabase vdb; 137 138 139 protected AbstractScheduler scheduler; 140 141 142 protected AbstractResultCache resultCache; 143 144 145 protected AbstractLoadBalancer loadBalancer; 146 147 148 protected RecoveryLog recoveryLog; 149 150 151 protected BackupManager backupManager; 152 153 protected DatabaseSchema dbs; 155 156 157 private boolean schemaIsDirty = false; 158 159 private boolean isCaseSensitiveParsing = false; 160 161 protected ParsingCache parsingCache = null; 162 163 private MetadataCache metadataCache = null; 164 165 protected int schedulerParsingranularity = ParsingGranularities.NO_PARSING; 168 169 private int cacheParsingranularity = ParsingGranularities.NO_PARSING; 170 171 private int loadBalancerParsingranularity = ParsingGranularities.NO_PARSING; 172 173 protected int requiredParsingGranularity = ParsingGranularities.NO_PARSING; 174 175 private long requestId = 0; 176 177 178 protected static Trace endUserLogger = Trace 179 .getLogger("org.continuent.sequoia.enduser"); 180 181 186 protected Hashtable transactionMetaDatas; 193 194 199 protected Hashtable tidSavepoints; 200 201 protected Trace logger = null; 202 203 private BackendStateListener backendStateListener; 204 205 209 223 public RequestManager(VirtualDatabase vdb, AbstractScheduler scheduler, 224 AbstractResultCache cache, AbstractLoadBalancer loadBalancer, 225 RecoveryLog recoveryLog, long beginTimeout, long commitTimeout, 226 long rollbackTimeout) throws SQLException , NotCompliantMBeanException 227 { 228 super(RequestManagerMBean.class); 229 this.vdb = vdb; 230 assignAndCheckSchedulerLoadBalancerValidity(scheduler, loadBalancer); 231 this.resultCache = cache; 233 if (resultCache != null) 234 { 235 cacheParsingranularity = cache.getParsingGranularity(); 236 if (cacheParsingranularity > requiredParsingGranularity) 237 requiredParsingGranularity = cacheParsingranularity; 238 } 239 setRecoveryLog(recoveryLog); 240 initRequestManagerVariables(vdb, beginTimeout, commitTimeout, 241 rollbackTimeout); 242 logger.info(Translate.get("requestmanager.parsing.granularity", 243 ParsingGranularities.getInformation(requiredParsingGranularity))); 244 245 try 246 { 247 MBeanServerManager.registerMBean(this, JmxConstants 248 .getRequestManagerObjectName(vdb.getVirtualDatabaseName())); 249 } 250 catch (Exception e) 251 { 252 logger.error(Translate.get("jmx.failed.register.mbean.requestmanager")); 253 } 254 } 255 256 260 public void initBackendsLastKnownCheckpointFromRecoveryLog() 261 { 262 if (recoveryLog == null) 263 return; 264 String databaseName = vdb.getVirtualDatabaseName(); 265 ArrayList backends = vdb.getBackends(); 266 int size = backends.size(); 267 DatabaseBackend backend; 268 BackendRecoveryInfo info; 269 for (int i = 0; i < size; i++) 270 { 271 backend = (DatabaseBackend) backends.get(i); 272 try 273 { 274 info = recoveryLog.getBackendRecoveryInfo(databaseName, backend 275 .getName()); 276 String checkpoint = info.getCheckpoint(); 277 if ((checkpoint == null) || ("".equals(checkpoint))) 278 { if (info.getBackendState() != BackendState.UNKNOWN) 280 { 281 String msg = "Backend " + backend.getName() 282 + " was not properly stopped, manual recovery will be needed (" 283 + info + ")"; 284 logger.warn(msg); 285 throw new SQLException (msg); 286 } 287 } 288 backend.setLastKnownCheckpoint(checkpoint); 289 } 290 catch (SQLException e) 291 { 292 logger.warn(e.getMessage(), e); 293 backend.setState(BackendState.UNKNOWN); 294 } 296 } 297 } 298 299 307 private void assignAndCheckSchedulerLoadBalancerValidity( 308 AbstractScheduler aScheduler, AbstractLoadBalancer aLoadBalancer) 309 throws SQLException 310 { 311 if (aScheduler == null) 312 throw new SQLException (Translate.get("requestmanager.null.scheduler")); 313 314 if (aLoadBalancer == null) 315 throw new SQLException (Translate.get("requestmanager.null.loadbalancer")); 316 317 if (aScheduler.getRAIDbLevel() != aLoadBalancer.getRAIDbLevel()) 318 throw new SQLException (Translate.get( 319 "requestmanager.incompatible.raidb.levels", new String []{ 320 "" + aScheduler.getRAIDbLevel(), 321 "" + aLoadBalancer.getRAIDbLevel()})); 322 323 setScheduler(aScheduler); 325 schedulerParsingranularity = aScheduler.getParsingGranularity(); 326 requiredParsingGranularity = schedulerParsingranularity; 327 setLoadBalancer(aLoadBalancer); 328 loadBalancerParsingranularity = aLoadBalancer.getParsingGranularity(); 329 if (loadBalancerParsingranularity > requiredParsingGranularity) 330 requiredParsingGranularity = loadBalancerParsingranularity; 331 } 332 333 340 public void getParsingFromCacheOrParse(AbstractRequest request) 341 throws SQLException 342 { 343 348 if ((requiredParsingGranularity != ParsingGranularities.NO_PARSING) 349 && (!request.isParsed())) 350 { 351 if (parsingCache == null) 352 { 353 SemanticManager semanticManager = vdb.getSemanticManager(); 354 request.setSemanticManager(semanticManager); 356 SemanticBehavior semantic = semanticManager.getRequestSemantic(request); 357 if (semantic != null) 358 request.setSemantic(semantic); 359 else 360 { request.parse(getDatabaseSchema(), requiredParsingGranularity, 362 isCaseSensitiveParsing); 363 } 364 } 365 else 366 parsingCache.getParsingFromCacheAndParseIfMissing(request); 367 } 368 } 369 370 378 private void initRequestManagerVariables(VirtualDatabase vdb, 379 long beginTimeout, long commitTimeout, long rollbackTimeout) 380 { 381 this.transactionMetaDatas = new Hashtable (); 382 this.tidSavepoints = new Hashtable (); 383 this.beginTimeout = beginTimeout; 384 this.commitTimeout = commitTimeout; 385 this.rollbackTimeout = rollbackTimeout; 386 this.vdb = vdb; 387 logger = Trace 388 .getLogger("org.continuent.sequoia.controller.RequestManager." 389 + vdb.getDatabaseName()); 390 } 391 392 396 402 public void closePersistentConnection(String login, 403 long persistentConnectionId) 404 { 405 try 406 { 407 scheduler.scheduleClosePersistentConnection(); 408 409 if (recoveryLog != null) 411 recoveryLog.logClosePersistentConnection(login, persistentConnectionId); 412 413 loadBalancer.closePersistentConnection(login, persistentConnectionId); 414 } 415 catch (NoMoreBackendException ignore) 416 { 417 } 419 catch (SQLException e) 420 { 421 logger.warn("Failed to close persistent connection " 422 + persistentConnectionId, e); 423 } 424 finally 425 { 426 scheduler.closePersistentConnectionCompleted(persistentConnectionId); 427 } 428 } 429 430 437 public boolean hasPersistentConnection(long persistentConnectionId) 438 { 439 return scheduler.hasPersistentConnection(persistentConnectionId); 440 } 441 442 450 public void openPersistentConnection(String login, long persistentConnectionId) 451 throws SQLException 452 { 453 boolean success = false; 454 long entryId = -1; 455 try 456 { 457 scheduler.scheduleOpenPersistentConnection(persistentConnectionId, login); 458 459 if (recoveryLog != null) 460 entryId = recoveryLog.logOpenPersistentConnection(login, 461 persistentConnectionId); 462 463 loadBalancer.openPersistentConnection(login, persistentConnectionId); 464 success = true; 465 } 466 catch (NoMoreBackendException e) 467 { 468 throw e; 469 } 470 catch (SQLException e) 471 { 472 logger.warn("Failed to open persistent connection " 473 + persistentConnectionId, e); 474 throw e; 475 } 476 finally 477 { 478 if (recoveryLog != null) 479 recoveryLog.logRequestCompletion(entryId, success, 0); 480 scheduler.openPersistentConnectionCompleted(persistentConnectionId, 481 success); 482 } 483 } 484 485 private static final Object REQUEST_ID_SYNC_OBJECT = new Object (); 486 487 493 public void initializeRequestId(long requestId) 494 { 495 this.requestId = requestId; 496 } 497 498 503 public long getNextRequestId() 504 { 505 synchronized (REQUEST_ID_SYNC_OBJECT) 506 { 507 return requestId++; 508 } 509 } 510 511 519 public ControllerResultSet statementExecuteQuery(SelectRequest request) 520 throws SQLException 521 { 522 TransactionMetaData tm = null; 524 if (!request.isAutoCommit()) 525 { Long tid = new Long (request.getTransactionId()); 527 try 528 { 529 tm = getTransactionMetaData(tid); 530 } 531 catch (SQLException e) 532 { 533 throw new SQLException (Translate.get("transaction.not.started", tid)); 534 } 535 } 536 537 getParsingFromCacheOrParse(request); 538 539 543 if (logger.isDebugEnabled()) 544 logger.debug(Translate.get("requestmanager.read.request.schedule", 545 new String []{String.valueOf(request.getId()), 546 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 547 548 scheduler.scheduleReadRequest(request); 550 551 555 ControllerResultSet result = null; 556 try 557 { if ((resultCache != null) && (!request.isMustBroadcast())) 559 { 560 if (logger.isDebugEnabled()) 561 logger.debug(Translate.get("requestmanager.read.request.cache.get", 562 new String []{String.valueOf(request.getId()), 563 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 564 565 AbstractResultCacheEntry qce = resultCache.getFromCache(request, true); 566 if (qce != null) 567 { 568 result = qce.getResult(); 569 if (result != null) 570 { if (vdb.getSQLMonitor() != null) 572 vdb.getSQLMonitor().logCacheHit(request); 573 574 scheduler.readCompleted(request); 575 return result; 576 } 577 } 578 } 579 580 584 if (logger.isDebugEnabled()) 585 logger.debug(Translate.get("requestmanager.read.request.balance", 586 new String []{String.valueOf(request.getId()), 587 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 588 589 591 result = loadBalancer.statementExecuteQuery(request, metadataCache); 593 594 598 if ((resultCache != null) 600 && (request.getCacheAbility() != RequestType.UNCACHEABLE)) 601 { 602 if (logger.isDebugEnabled()) 603 logger.debug(Translate.get( 604 "requestmanager.read.request.cache.update", new String []{ 605 String.valueOf(request.getId()), 606 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 607 608 resultCache.addToCache(request, result); 609 if (tm != null) 610 tm.setAltersQueryResultCache(true); 611 } 612 } 613 catch (Exception failed) 614 { 615 if (resultCache != null) 616 resultCache.removeFromPendingQueries(request); 617 if (failed instanceof NoMoreBackendException) 618 throw (NoMoreBackendException) failed; 619 String msg = Translate.get("requestmanager.request.failed", new String []{ 620 request.getSqlShortForm(vdb.getSqlShortFormLength()), 621 failed.getMessage()}); 622 if (failed instanceof RuntimeException ) 623 logger.warn(msg, failed); 624 else 625 logger.warn(msg); 626 if (failed instanceof SQLException ) 627 throw (SQLException ) failed; 628 629 throw new SQLException (msg); 630 } 631 finally 632 { 633 scheduler.readCompleted(request); 635 } 636 return result; 637 } 638 639 648 public ExecuteUpdateResult statementExecuteUpdate(AbstractWriteRequest request) 649 throws SQLException 650 { 651 boolean hasBeenScheduled = false, schedulerHasBeenNotified = false; 652 try 653 { 654 scheduleExecWriteRequest(request); 655 hasBeenScheduled = true; 656 ExecuteUpdateResult execWriteRequestResult = null; 657 try 658 { 659 execWriteRequestResult = loadBalanceStatementExecuteUpdate(request); 660 } 661 catch (AllBackendsFailedException e) 662 { 663 String msg = Translate 664 .get("requestmanager.write.request.failed.unexpected"); 665 logger.fatal(msg, e); 666 endUserLogger.fatal(msg); 667 throw new RuntimeException (msg, e); 668 } 669 updateAndNotifyExecWriteRequest(request, execWriteRequestResult 670 .getUpdateCount()); 671 schedulerHasBeenNotified = true; 672 return execWriteRequestResult; 673 } 674 finally 675 { 676 if (hasBeenScheduled && !schedulerHasBeenNotified) 677 scheduler.writeCompleted(request); 678 } 679 } 680 681 690 public GeneratedKeysResult statementExecuteUpdateWithKeys( 691 AbstractWriteRequest request) throws SQLException 692 { 693 boolean hasBeenScheduled = false, schedulerHasBeenNotified = false; 694 try 695 { 696 scheduleExecWriteRequest(request); 697 hasBeenScheduled = true; 698 GeneratedKeysResult execWriteRequestWithKeysResult = null; 699 try 700 { 701 execWriteRequestWithKeysResult = loadBalanceStatementExecuteUpdateWithKeys(request); 702 } 703 catch (AllBackendsFailedException e) 704 { 705 String msg = Translate 706 .get("requestmanager.write.request.keys.failed.unexpected"); 707 logger.fatal(msg, e); 708 endUserLogger.fatal(msg); 709 throw new RuntimeException (msg, e); 710 } 711 updateAndNotifyExecWriteRequest(request, execWriteRequestWithKeysResult 712 .getUpdateCount()); 713 schedulerHasBeenNotified = true; 714 return execWriteRequestWithKeysResult; 715 } 716 finally 717 { 718 if (hasBeenScheduled && !schedulerHasBeenNotified) 719 scheduler.writeCompleted(request); 720 } 721 } 722 723 733 public ExecuteResult statementExecute(AbstractRequest request) 734 throws AllBackendsFailedException, SQLException 735 { 736 StoredProcedure proc = new StoredProcedure(request.getSqlOrTemplate(), 738 request.getEscapeProcessing(), request.getTimeout(), request 739 .getLineSeparator()); 740 proc.setIsAutoCommit(request.isAutoCommit()); 741 proc.setTransactionId(request.getTransactionId()); 742 proc.setTransactionIsolation(request.getTransactionIsolation()); 743 proc.setId(request.getId()); 744 proc.setLogin(request.getLogin()); 745 proc.setPreparedStatementParameters(request 746 .getPreparedStatementParameters()); 747 proc.setTimeout(request.getTimeout()); 748 proc.setMaxRows(request.getMaxRows()); 749 proc.setPersistentConnection(request.isPersistentConnection()); 750 proc.setPersistentConnectionId(request.getPersistentConnectionId()); 751 752 boolean hasBeenScheduled = false; 753 try 754 { 755 ExecuteResult result; 756 757 scheduleStoredProcedure(proc); 759 hasBeenScheduled = true; 760 761 if (logger.isDebugEnabled()) 762 logger.debug(Translate.get("requestmanager.write.stored.procedure", 763 new String []{String.valueOf(request.getId()), 764 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 765 766 result = loadBalanceStatementExecute(proc); 767 768 updateRecoveryLogFlushCacheAndRefreshSchema(proc); 769 770 scheduler.storedProcedureCompleted(proc); 772 773 return result; 774 } 775 catch (AllBackendsFailedException e) 776 { 777 throw e; 778 } 779 finally 780 { 781 if (hasBeenScheduled) 782 scheduler.storedProcedureCompleted(proc); 783 } 784 } 785 786 792 public void scheduleExecWriteRequest(AbstractWriteRequest request) 793 throws SQLException 794 { 795 if (!request.isAutoCommit()) 797 { long tid = request.getTransactionId(); 800 if (!transactionMetaDatas.containsKey(new Long (tid))) 801 throw new SQLException (Translate.get("transaction.not.started", tid)); 802 } 803 804 getParsingFromCacheOrParse(request); 805 806 810 if (logger.isDebugEnabled()) 811 logger.debug(Translate.get("requestmanager.write.request.schedule", 812 new String []{String.valueOf(request.getId()), 813 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 814 815 try 817 { 818 scheduler.scheduleWriteRequest(request); 819 } 820 catch (RollbackException e) 821 { rollback(request.getTransactionId(), true); 823 throw new SQLException (e.getMessage()); 824 } 825 } 826 827 839 public GeneratedKeysResult loadBalanceStatementExecuteUpdateWithKeys( 840 AbstractWriteRequest request) throws AllBackendsFailedException, 841 NoMoreBackendException, SQLException 842 { 843 if (logger.isDebugEnabled()) 844 logger.debug(Translate.get("requestmanager.write.request.balance", 845 new String []{String.valueOf(request.getId()), 846 String.valueOf(request.getTransactionId()), 847 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 848 849 try 850 { return loadBalancer 852 .statementExecuteUpdateWithKeys(request, metadataCache); 853 } 854 catch (Exception failed) 855 { 856 if (!vdb.isDistributed()) 857 { if (recoveryLog != null) 859 recoveryLog.logRequestCompletion(request.getLogId(), false, request 860 .getExecTimeInMs()); 861 } 862 863 String msg = Translate.get("requestmanager.request.failed", new String []{ 864 request.getSqlShortForm(vdb.getSqlShortFormLength()), 865 failed.getMessage()}); 866 if (failed instanceof RuntimeException ) 867 logger.warn(msg, failed); 868 869 if (failed instanceof AllBackendsFailedException) 870 throw (AllBackendsFailedException) failed; 871 else if (failed instanceof SQLException ) 872 throw (SQLException ) failed; 873 else if (failed instanceof NoMoreBackendException) 874 throw (NoMoreBackendException) failed; 875 else 876 throw new SQLException (msg); 877 } 878 } 879 880 892 public ExecuteUpdateResult loadBalanceStatementExecuteUpdate( 893 AbstractWriteRequest request) throws AllBackendsFailedException, 894 NoMoreBackendException, SQLException 895 { 896 if (logger.isDebugEnabled()) 897 logger.debug(Translate.get("requestmanager.write.request.balance", 898 new String []{String.valueOf(request.getId()), 899 String.valueOf(request.getTransactionId()), 900 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 901 902 try 903 { if (request.isUpdate() && (resultCache != null)) 905 { if (!resultCache.isUpdateNecessary((UpdateRequest) request)) 908 return new ExecuteUpdateResult(0); 909 } 910 return loadBalancer.statementExecuteUpdate(request); 911 } 912 catch (Exception failed) 913 { 914 if (!vdb.isDistributed()) 915 { if (recoveryLog != null) 917 recoveryLog.logRequestCompletion(request.getLogId(), false, request 918 .getExecTimeInMs()); 919 } 920 921 String msg = Translate.get("requestmanager.request.failed", new String []{ 922 request.getSqlShortForm(vdb.getSqlShortFormLength()), 923 failed.getMessage()}); 924 925 if (failed instanceof RuntimeException ) 927 logger.warn(msg, failed); 928 929 if (failed instanceof AllBackendsFailedException) 931 throw (AllBackendsFailedException) failed; 932 else if (failed instanceof SQLException ) 933 throw (SQLException ) failed; 934 else if (failed instanceof NoMoreBackendException) 935 throw (NoMoreBackendException) failed; 936 else 937 throw new SQLException (msg); 938 } 939 } 940 941 951 public ExecuteResult loadBalanceStatementExecute(AbstractRequest request) 952 throws AllBackendsFailedException, SQLException 953 { 954 ExecuteResult result; 955 959 if (resultCache != null) 961 { 962 resultCache.flushCache(); 963 } 964 965 969 try 970 { result = loadBalancer.statementExecute(request, metadataCache); 972 return result; 973 } 974 catch (Exception failed) 975 { 976 if (!vdb.isDistributed()) 977 { if (recoveryLog != null) 979 recoveryLog.logRequestCompletion(request.getLogId(), false, request 980 .getExecTimeInMs()); 981 } 982 983 String msg = Translate.get("requestmanager.request.failed", new String []{ 984 request.getSqlShortForm(vdb.getSqlShortFormLength()), 985 failed.getMessage()}); 986 if (failed instanceof RuntimeException ) 987 logger.warn(msg, failed); 988 989 if (failed instanceof AllBackendsFailedException) 990 throw (AllBackendsFailedException) failed; 991 else if (failed instanceof SQLException ) 992 throw (SQLException ) failed; 993 else if (failed instanceof NoMoreBackendException) 994 throw (NoMoreBackendException) failed; 995 else 996 throw (SQLException ) new SQLException (msg).initCause(failed); 997 } 998 } 999 1000 1010 public void updateAndNotifyExecWriteRequest(AbstractWriteRequest request, 1011 int updateCount) throws SQLException 1012 { 1013 try 1014 { 1015 TransactionMetaData tm = null; 1016 if (!request.isAutoCommit()) 1017 { 1018 1022 tm = getTransactionMetaData(new Long (request.getTransactionId())); 1023 tm.setReadOnly(false); 1024 } 1025 1026 if ((recoveryLog != null) 1028 && (loadBalancer.getRAIDbLevel() != RAIDbLevels.SingleDB)) 1029 recoveryLog.logRequestExecuteUpdateCompletion(request.getLogId(), true, 1030 updateCount, request.getExecTimeInMs()); 1031 1032 if (requiredParsingGranularity == ParsingGranularities.NO_PARSING) 1033 return; 1034 1035 if (request.altersSomething()) 1036 { 1037 SemanticBehavior semantic = request.getSemantic(); 1038 if (semantic == null) 1039 { logger.warn("No semantic information found for request '" 1041 + request.getSqlShortForm(vdb.getSqlShortFormLength()) 1042 + "' flushing all caches and refreshing schema."); 1043 1044 flushAllCachesAndUpdateTransactionMetadata(tm); 1045 return; 1046 } 1047 1048 1050 if (((semantic.altersDatabaseSchema()) || semantic 1053 .altersQueryResultCache()) 1054 && (resultCache != null)) 1055 { 1056 if (logger.isDebugEnabled()) 1057 logger.debug(Translate.get( 1058 "requestmanager.write.request.cache.update", new String []{ 1059 String.valueOf(request.getId()), 1060 request.getSqlShortForm(vdb.getSqlShortFormLength())})); 1061 1062 if (semantic.altersDatabaseSchema() && tm != null) 1063 tm.setAltersQueryResultCache(true); 1064 resultCache.writeNotify(request); 1065 } 1066 1067 if (tm != null) 1068 tm.setAltersDatabaseSchema(true); 1069 1070 synchronized (this) 1071 { 1072 if (getDatabaseSchema() != null) 1073 getDatabaseSchema().updateDatabaseSchema(request, logger, this, tm, 1074 null); 1075 } 1076 1077 if (semantic.altersMetadataCache()) 1078 { 1079 flushMetadataCacheAndUpdateTransactionMetadata(tm); 1080 } 1081 } 1082 } 1083 catch (Exception failed) 1084 { 1085 String msg = Translate.get("requestmanager.request.failed", new String []{ 1086 request.getSqlShortForm(vdb.getSqlShortFormLength()), 1087 failed.getMessage()}); 1088 if (failed instanceof RuntimeException ) 1089 logger.warn(msg, failed); 1090 else 1091 logger.warn(msg); 1092 throw new SQLException (msg); 1093 } 1094 finally 1095 { 1096 scheduler.writeCompleted(request); 1098 } 1099 } 1100 1101 1110 public ControllerResultSet callableStatementExecuteQuery(StoredProcedure proc) 1111 throws AllBackendsFailedException, SQLException 1112 { 1113 ControllerResultSet result = null; 1114 boolean hasBeenScheduled = false; 1115 boolean success = false; 1116 try 1117 { 1118 scheduleStoredProcedure(proc); 1119 hasBeenScheduled = true; 1120 1121 if (logger.isDebugEnabled()) 1122 logger.debug(Translate.get("requestmanager.read.stored.procedure", 1123 new String []{String.valueOf(proc.getId()), 1124 proc.getSqlShortForm(vdb.getSqlShortFormLength())})); 1125 1126 result = loadBalanceCallableStatementExecuteQuery(proc); 1127 1128 updateRecoveryLogFlushCacheAndRefreshSchema(proc); 1129 1130 success = true; 1131 return result; 1132 } 1133 catch (AllBackendsFailedException e) 1134 { 1135 throw e; 1136 } 1137 catch (NoMoreBackendException e) 1138 { 1139 throw e; 1140 } 1141 catch (Exception failed) 1142 { 1143 String msg = Translate.get("requestmanager.stored.procedure.failed", 1144 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1145 failed.getMessage()}); 1146 logger.warn(msg); 1147 if (failed instanceof SQLException ) 1148 { 1149 throw (SQLException ) failed; 1150 } 1151 throw new SQLException (msg); 1152 } 1153 finally 1154 { 1155 if (hasBeenScheduled) 1156 scheduler.storedProcedureCompleted(proc); 1157 if (!vdb.isDistributed() && !success) 1158 { if (recoveryLog != null) 1160 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 1161 .getExecTimeInMs()); 1162 } 1163 } 1164 } 1165 1166 1175 public ExecuteUpdateResult callableStatementExecuteUpdate(StoredProcedure proc) 1176 throws AllBackendsFailedException, SQLException 1177 { 1178 ExecuteUpdateResult result; 1179 boolean hasBeenScheduled = false; 1180 boolean success = false; 1181 try 1182 { 1183 scheduleStoredProcedure(proc); 1185 hasBeenScheduled = true; 1186 1187 if (logger.isDebugEnabled()) 1188 logger.debug(Translate.get("requestmanager.write.stored.procedure", 1189 new String []{String.valueOf(proc.getId()), 1190 proc.getSqlShortForm(vdb.getSqlShortFormLength())})); 1191 1192 result = loadBalanceCallableStatementExecuteUpdate(proc); 1193 1194 updateRecoveryLogFlushCacheAndRefreshSchema(proc); 1195 1196 scheduler.storedProcedureCompleted(proc); 1198 1199 success = true; 1200 return result; 1201 } 1202 catch (AllBackendsFailedException e) 1203 { 1204 throw e; 1205 } 1206 catch (Exception failed) 1207 { 1208 String msg = Translate.get("requestmanager.stored.procedure.failed", 1209 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1210 failed.getMessage()}); 1211 logger.warn(msg); 1212 if (failed instanceof SQLException ) 1213 { 1214 throw (SQLException ) failed; 1215 } 1216 throw new SQLException (msg); 1217 } 1218 finally 1219 { 1220 if (hasBeenScheduled) 1221 scheduler.storedProcedureCompleted(proc); 1222 if (!vdb.isDistributed() && !success) 1223 { if (recoveryLog != null) 1225 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 1226 .getExecTimeInMs()); 1227 } 1228 } 1229 } 1230 1231 1241 public ExecuteResult callableStatementExecute(StoredProcedure proc) 1242 throws AllBackendsFailedException, SQLException 1243 { 1244 ExecuteResult result; 1245 boolean hasBeenScheduled = false; 1246 boolean success = false; 1247 try 1248 { 1249 scheduleStoredProcedure(proc); 1250 hasBeenScheduled = true; 1251 1252 if (logger.isDebugEnabled()) 1253 logger.debug(Translate.get("requestmanager.write.stored.procedure", 1254 new String []{String.valueOf(proc.getId()), 1255 proc.getSqlShortForm(vdb.getSqlShortFormLength())})); 1256 1257 result = loadBalanceCallableStatementExecute(proc); 1258 1259 updateRecoveryLogFlushCacheAndRefreshSchema(proc); 1260 1261 success = true; 1262 return result; 1263 } 1264 catch (AllBackendsFailedException e) 1265 { 1266 throw e; 1267 } 1268 catch (NoMoreBackendException e) 1269 { 1270 throw e; 1271 } 1272 catch (Exception failed) 1273 { 1274 String msg = Translate.get("requestmanager.stored.procedure.failed", 1275 new String []{proc.getSqlShortForm(vdb.getSqlShortFormLength()), 1276 failed.getMessage()}); 1277 logger.warn(msg); 1278 if (failed instanceof SQLException ) 1279 { 1280 throw (SQLException ) failed; 1281 } 1282 throw new SQLException (msg); 1283 } 1284 finally 1285 { 1286 if (hasBeenScheduled) 1287 scheduler.storedProcedureCompleted(proc); 1288 if (!vdb.isDistributed() && !success) 1289 { if (recoveryLog != null) 1291 recoveryLog.logRequestCompletion(proc.getLogId(), false, proc 1292 .getExecTimeInMs()); 1293 } 1294 } 1295 } 1296 1297 1306 public void scheduleStoredProcedure(StoredProcedure proc) throws SQLException 1307 { 1308 if (!proc.isAutoCommit()) 1310 { long tid = proc.getTransactionId(); 1312 if (!transactionMetaDatas.containsKey(new Long (tid))) 1313 throw new SQLException (Translate.get("transaction.not.started", tid)); 1314 } 1315 1316 getParsingFromCacheOrParse(proc); 1317 1318 1322 try 1324 { 1325 scheduler.scheduleStoredProcedure(proc); 1326 } 1327 catch (RollbackException e) 1328 { rollback(proc.getTransactionId(), true); 1330 throw new SQLException (e.getMessage()); 1331 } 1332 } 1333 1334 1344 public ControllerResultSet loadBalanceCallableStatementExecuteQuery( 1345 StoredProcedure proc) throws SQLException , AllBackendsFailedException 1346 { 1347 SemanticBehavior semantic = proc.getSemantic(); 1348 ControllerResultSet result; 1349 1350 1354 if ((resultCache != null) && (!proc.isReadOnly())) 1359 { 1360 if ((semantic == null) || (!semantic.isReadOnly())) 1361 resultCache.flushCache(); 1362 } 1363 1364 1368 if (proc.isReadOnly() || ((semantic != null) && (semantic.isReadOnly()))) 1370 result = loadBalancer.readOnlyCallableStatementExecuteQuery(proc, 1371 metadataCache); 1372 else 1373 { 1374 proc.setFetchSize(0); 1376 result = loadBalancer.callableStatementExecuteQuery(proc, metadataCache); 1377 } 1378 return result; 1379 } 1380 1381 1391 public ExecuteUpdateResult loadBalanceCallableStatementExecuteUpdate( 1392 StoredProcedure proc) throws AllBackendsFailedException, SQLException 1393 { 1394 ExecuteUpdateResult result; 1395 1399 if (resultCache != null) 1401 { 1402 SemanticBehavior semantic = proc.getSemantic(); 1403 if ((semantic == null) || (!semantic.isReadOnly())) 1404 resultCache.flushCache(); 1405 } 1406 1407 1411 result = loadBalancer.callableStatementExecuteUpdate(proc); 1413 return result; 1414 } 1415 1416 1426 public ExecuteResult loadBalanceCallableStatementExecute(StoredProcedure proc) 1427 throws AllBackendsFailedException, SQLException 1428 { 1429 SemanticBehavior semantic = proc.getSemantic(); 1430 ExecuteResult result; 1431 1432 1436 if (resultCache != null) 1438 { 1439 if ((semantic == null) || (!semantic.isReadOnly())) 1440 resultCache.flushCache(); 1441 } 1442 1443 1447 if (proc.isReadOnly() || ((semantic != null) && (semantic.isReadOnly()))) 1449 result = loadBalancer.readOnlyCallableStatementExecute(proc, 1450 metadataCache); 1451 else 1452 result = loadBalancer.callableStatementExecute(proc, metadataCache); 1453 return result; 1454 } 1455 1456 1463 public void updateRecoveryLogFlushCacheAndRefreshSchema(StoredProcedure proc) 1464 throws SQLException 1465 { 1466 if (proc.isReadOnly()) 1469 return; 1470 1471 SemanticBehavior semantic = proc.getSemantic(); 1472 TransactionMetaData tm = null; 1473 if (!proc.isAutoCommit()) 1474 tm = getTransactionMetaData(new Long (proc.getTransactionId())); 1475 1476 if ((semantic == null) || (semantic.altersDatabaseSchema())) 1477 { 1478 if ((semantic == null) && (logger.isDebugEnabled())) 1480 logger.debug("No semantic found for stored procedure " 1481 + proc.getSqlShortForm(vdb.getSqlShortFormLength()) 1482 + ". Forcing a schema refresh."); 1483 setSchemaIsDirty(true); 1484 1485 if (tm != null) 1486 tm.setAltersDatabaseSchema(true); 1487 } 1488 1489 if ((semantic == null) || (!semantic.isReadOnly())) 1490 { 1491 if ((recoveryLog != null) 1493 && (loadBalancer.getRAIDbLevel() != RAIDbLevels.SingleDB)) 1494 recoveryLog.logRequestCompletion(proc.getLogId(), true, proc 1495 .getExecTimeInMs()); 1496 1497 if (tm != null) 1503 { 1504 tm.setReadOnly(false); 1505 tm.setAltersQueryResultCache(true); 1506 } 1507 1508 1512 if (resultCache != null) 1513 resultCache.writeNotify(proc); 1514 1515 if ((metadataCache != null) 1516 && ((semantic == null) || (semantic.altersDatabaseSchema()))) 1517 metadataCache.flushCache(); 1518 } 1519 } 1520 1521 1529 public ControllerResultSet getPreparedStatementGetMetaData( 1530 AbstractRequest request) throws SQLException 1531 { 1532 return loadBalancer.getPreparedStatementGetMetaData(request); 1533 } 1534 1535 1539 1556 public long begin(String login, boolean isPersistentConnection, 1557 long persistentConnectionId) throws SQLException 1558 { 1559 long tid = scheduler.getNextTransactionId(); 1560 doBegin(login, tid, isPersistentConnection, persistentConnectionId); 1561 return tid; 1562 } 1563 1564 1577 public void doBegin(String login, long tid, boolean isPersistentConnection, 1578 long persistentConnectionId) throws SQLException 1579 { 1580 try 1581 { 1582 TransactionMetaData tm = new TransactionMetaData(tid, beginTimeout, 1583 login, isPersistentConnection, persistentConnectionId); 1584 scheduler.begin(tm, false, null); 1585 1586 if (logger.isDebugEnabled()) 1587 logger.debug(Translate.get("transaction.begin", String.valueOf(tid))); 1588 1589 try 1590 { 1591 loadBalancer.begin(tm); 1593 transactionMetaDatas.put(new Long (tid), tm); 1597 } 1598 catch (SQLException e) 1599 { 1600 throw e; 1601 } 1602 finally 1603 { 1604 scheduler.beginCompleted(tid); 1606 } 1607 } 1608 catch (RuntimeException e) 1609 { 1610 String msg = Translate 1611 .get("fatal.runtime.exception.requestmanager.begin"); 1612 logger.fatal(msg, e); 1613 endUserLogger.fatal(msg); 1614 throw new SQLException (e.getMessage()); 1615 } 1616 } 1617 1618 1630 public void logLazyTransactionBegin(long transactionId) throws SQLException 1631 { 1632 try 1633 { 1634 Long tid = new Long (transactionId); 1635 TransactionMetaData tm = getTransactionMetaData(tid); 1636 1637 if (logger.isDebugEnabled()) 1638 logger.debug(Translate.get("transaction.begin.log", String 1639 .valueOf(transactionId))); 1640 1641 if (recoveryLog != null) 1643 recoveryLog.logBegin(tm); 1644 } 1645 catch (RuntimeException e) 1646 { 1647 String msg = Translate 1648 .get("fatal.runtime.exception.requestmanager.begin.log"); 1649 logger.fatal(msg, e); 1650 endUserLogger.fatal(msg); 1651 throw new SQLException (e.getMessage()); 1652 } 1653 } 1654 1655 1675 public void abort(long transactionId, boolean logAbort, boolean forceAbort) 1676 throws SQLException 1677 { 1678 TransactionMetaData tm; 1679 try 1680 { 1681 Long tid = new Long (transactionId); 1682 boolean tmIsFake = false; 1683 try 1684 { 1685 tm = getTransactionMetaData(tid); 1686 if (!forceAbort && tidSavepoints.get(tid) != null) 1687 { 1688 if (logger.isDebugEnabled()) 1689 logger.debug("Transaction " + transactionId 1690 + " has savepoints, transaction will not be aborted"); 1691 return; 1692 } 1693 } 1694 catch (SQLException e1) 1695 { 1696 logger.warn("No transaction metadata found to abort transaction " 1697 + transactionId + ". Creating a fake context for abort."); 1698 tm = new TransactionMetaData(transactionId, 0, 1701 RecoveryLog.UNKNOWN_USER, false, 0); 1702 tm.setReadOnly(!logAbort); 1703 tmIsFake = true; 1704 if (tidSavepoints.get(tid) != null) 1705 { 1706 if (logger.isDebugEnabled()) 1707 logger.debug("Transaction " + transactionId 1708 + " has savepoints, transaction will not be aborted"); 1709 return; 1710 } 1711 } 1712 1713 VirtualDatabaseWorkerThread vdbwt = vdb 1714 .getVirtualDatabaseWorkerThreadForTransaction(transactionId); 1715 if (vdbwt != null) 1716 vdbwt.notifyAbort(transactionId); 1717 1718 if (logger.isDebugEnabled()) 1719 logger.debug(Translate.get("transaction.aborting", String 1720 .valueOf(transactionId))); 1721 1722 1725 boolean abortScheduled = false; 1726 try 1727 { 1728 if (!tmIsFake) 1729 { 1730 scheduler.rollback(tm, null); 1731 abortScheduled = true; 1732 } 1733 1734 loadBalancer.abort(tm); 1735 1736 if (recoveryLog != null) 1738 recoveryLog.logRequestCompletion(tm.getLogId(), true, 0); 1739 1740 if ((resultCache != null) 1743 && (tm.altersQueryResultCache() || tm.altersDatabaseSchema())) 1744 resultCache.rollback(transactionId); 1745 1746 if (tm.altersDatabaseSchema()) 1748 { 1749 if (metadataCache != null) 1750 metadataCache.flushCache(); 1751 setSchemaIsDirty(true); 1752 } 1753 } 1754 1755 catch (NoMoreBackendException e) 1762 { 1763 if (getRecoveryLog() != null) 1766 { 1767 if (logger.isDebugEnabled()) 1768 logger.debug(Translate 1769 .get("virtualdatabase.distributed.abort.logging.only", 1770 transactionId)); 1771 1772 DistributedRollback totalOrderAbort = new DistributedRollback(tm 1774 .getLogin(), transactionId); 1775 if (getLoadBalancer().waitForTotalOrder(totalOrderAbort, false)) 1776 getLoadBalancer().removeObjectFromAndNotifyTotalOrderQueue( 1777 totalOrderAbort); 1778 1779 this.getRecoveryLog().logRequestCompletion(tm.getLogId(), false, 0); 1781 e.setRecoveryLogId(tm.getLogId()); 1782 e.setLogin(tm.getLogin()); 1783 } 1784 throw e; 1785 } 1786 1787 catch (SQLException e) 1788 { 1789 1793 DistributedRollback totalOrderAbort = new DistributedRollback(tm 1794 .getLogin(), transactionId); 1795 if (loadBalancer.waitForTotalOrder(totalOrderAbort, false)) 1796 loadBalancer 1797 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderAbort); 1798 1799 if (recoveryLog != null) 1801 recoveryLog.logRequestCompletion(tm.getLogId(), false, 0); 1802 1803 throw e; 1804 } 1805 finally 1806 { 1807 if (abortScheduled) { 1809 scheduler.rollbackCompleted(tm, true); 1811 } 1812 1813 completeTransaction(tid); 1814 1815 if (logger.isDebugEnabled()) 1816 logger.debug(Translate.get("transaction.aborted", String 1817 .valueOf(transactionId))); 1818 } 1819 } 1820 catch (RuntimeException e) 1821 { 1822 String msg = Translate 1823 .get("fatal.runtime.exception.requestmanager.abort"); 1824 logger.fatal(msg, e); 1825 endUserLogger.fatal(msg); 1826 throw new SQLException (e.getMessage()); 1827 } 1828 } 1829 1830 1837 public TransactionMetaData getTransactionMetaData(Long tid) 1838 throws SQLException 1839 { 1840 TransactionMetaData tm = (TransactionMetaData) transactionMetaDatas 1841 .get(tid); 1842 1843 if (tm == null) 1844 throw new SQLException (Translate.get("transaction.marker.not.found", 1845 String.valueOf(tid))); 1846 1847 return tm; 1848 } 1849 1850 1855 public void completeTransaction(Long tid) 1856 { 1857 if (loadBalancer.waitForCompletionPolicy.getPolicy() == WaitForCompletionPolicy.ALL) 1858 { 1859 transactionMetaDatas.remove(tid); 1860 tidSavepoints.remove(tid); 1861 } 1862 else 1863 { TransactionMetaData tm = (TransactionMetaData) transactionMetaDatas 1866 .get(tid); 1867 if (tm != null) 1868 { if (tm.isLockedByBackends()) 1870 { 1871 return; 1872 } 1873 transactionMetaDatas.remove(tid); 1874 } 1875 tidSavepoints.remove(tid); 1876 } 1877 } 1878 1879 1888 public void commit(long transactionId, boolean logCommit, 1889 boolean emptyTransaction) throws SQLException 1890 { 1891 long startTime = System.currentTimeMillis(); 1892 try 1893 { 1894 Long tid = new Long (transactionId); 1895 TransactionMetaData tm = getTransactionMetaData(tid); 1896 1897 boolean commitScheduled = false; 1898 boolean success = false; 1899 try 1900 { 1901 scheduler.commit(tm, emptyTransaction, null); 1902 commitScheduled = true; 1903 if (!emptyTransaction) 1904 { 1905 if (logger.isDebugEnabled()) 1906 logger.debug(Translate.get("transaction.commit", String 1907 .valueOf(tid))); 1908 1909 loadBalancer.commit(tm); 1911 1912 if (resultCache != null) 1914 resultCache.commit(tm.getTransactionId()); 1915 } 1916 success = true; 1917 } 1918 catch (SQLException e) 1919 { 1920 1924 DistributedCommit totalOrderCommit = new DistributedCommit(tm 1925 .getLogin(), transactionId); 1926 if (loadBalancer.waitForTotalOrder(totalOrderCommit, false)) 1927 loadBalancer 1928 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderCommit); 1929 1930 throw e; 1931 } 1932 catch (AllBackendsFailedException e) 1933 { 1934 String msg = "All backends failed to commit transaction " 1935 + transactionId + " (" + e + ")"; 1936 logger.error(msg); 1937 throw new SQLException (msg); 1938 } 1939 finally 1940 { 1941 if (recoveryLog != null && tm.getLogId() != 0) 1945 recoveryLog.logRequestCompletion(tm.getLogId(), success, System 1946 .currentTimeMillis() 1947 - startTime); 1948 if (commitScheduled) 1949 { 1950 scheduler.commitCompleted(tm, success); 1952 } 1953 if (success) 1954 { 1955 completeTransaction(tid); 1956 } 1957 } 1958 } 1959 catch (RuntimeException e) 1960 { 1961 String msg = Translate 1962 .get("fatal.runtime.exception.requestmanager.commit"); 1963 logger.fatal(msg, e); 1964 endUserLogger.fatal(msg); 1965 throw new SQLException (e.getMessage()); 1966 } 1967 } 1968 1969 1977 public void rollback(long transactionId, boolean logRollback) 1978 throws SQLException 1979 { 1980 long startTime = System.currentTimeMillis(); 1981 try 1982 { 1983 Long tid = new Long (transactionId); 1984 TransactionMetaData tm = getTransactionMetaData(tid); 1985 1986 1988 boolean rollbackScheduled = false; 1989 boolean success = false; 1990 try 1991 { 1992 scheduler.rollback(tm, null); 1993 rollbackScheduled = true; 1994 1995 if (logger.isDebugEnabled()) 1996 logger.debug(Translate.get("transaction.rollback", String 1997 .valueOf(transactionId))); 1998 1999 loadBalancer.rollback(tm); 2001 2002 if ((resultCache != null) 2005 && (tm.altersQueryResultCache() || tm.altersDatabaseSchema())) 2006 resultCache.rollback(transactionId); 2007 2008 if (tm.altersDatabaseSchema()) 2010 { 2011 if (metadataCache != null) 2012 metadataCache.flushCache(); 2013 setSchemaIsDirty(true); 2014 } 2015 2016 success = true; 2017 } 2018 catch (SQLException e) 2019 { 2020 2024 DistributedRollback totalOrderRollback = new DistributedRollback(tm 2025 .getLogin(), transactionId); 2026 if (loadBalancer.waitForTotalOrder(totalOrderRollback, false)) 2027 { 2028 loadBalancer 2029 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderRollback); 2030 } 2031 else if (recoveryLog != null) 2032 { if (!recoveryLog.findRollbackForTransaction(tm.getTransactionId())) 2036 recoveryLog.logRollback(tm); 2037 if (!rollbackScheduled) 2038 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2039 .currentTimeMillis() 2040 - startTime); 2041 } 2042 2043 throw e; 2044 } 2045 catch (AllBackendsFailedException e) 2046 { 2047 String msg = Translate.get("requestmanager.rollback.failed.all", 2048 new String []{String.valueOf(transactionId), e.getMessage()}); 2049 logger.error(msg); 2050 throw new SQLException (msg); 2051 } 2052 finally 2053 { 2054 if (rollbackScheduled) 2055 { 2056 if (recoveryLog != null) 2058 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2059 .currentTimeMillis() 2060 - startTime); 2061 2062 scheduler.rollbackCompleted(tm, success); 2064 } 2065 2066 completeTransaction(tid); 2067 } 2068 } 2069 catch (RuntimeException e) 2070 { 2071 String msg = Translate 2072 .get("fatal.runtime.exception.requestmanager.rollback"); 2073 logger.fatal(msg, e); 2074 endUserLogger.fatal(msg); 2075 throw new SQLException (e.getMessage()); 2076 } 2077 } 2078 2079 2086 public void rollback(long transactionId, String savepointName) 2087 throws SQLException 2088 { 2089 long startTime = System.currentTimeMillis(); 2090 try 2091 { 2092 Long tid = new Long (transactionId); 2093 TransactionMetaData tm = getTransactionMetaData(tid); 2094 2095 boolean rollbackScheduled = false; 2096 boolean validSavepoint = false; 2097 2098 try 2099 { 2100 if (!hasSavepoint(tid, savepointName)) 2102 throw new SQLException (Translate.get( 2103 "transaction.savepoint.not.found", new String []{savepointName, 2104 String.valueOf(transactionId)})); 2105 2106 validSavepoint = true; 2107 2108 scheduler.rollback(tm, savepointName, null); 2110 rollbackScheduled = true; 2111 2112 if (logger.isDebugEnabled()) 2113 logger.debug(Translate.get("transaction.rollbacksavepoint", 2114 new String []{String.valueOf(transactionId), savepointName})); 2115 2116 loadBalancer.rollbackToSavepoint(tm, savepointName); 2118 2119 if (recoveryLog != null) 2121 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2122 .currentTimeMillis() 2123 - startTime); 2124 2125 if ((resultCache != null) 2128 && (tm.altersQueryResultCache() || tm.altersDatabaseSchema())) 2129 resultCache.rollback(transactionId); 2130 2131 if (tm.altersDatabaseSchema()) 2133 { 2134 if (metadataCache != null) 2135 metadataCache.flushCache(); 2136 setSchemaIsDirty(true); 2137 } 2138 } 2139 catch (SQLException e) 2140 { 2141 2145 DistributedRollbackToSavepoint totalOrderRollbackToSavepoint = new DistributedRollbackToSavepoint( 2146 transactionId, savepointName); 2147 if (loadBalancer 2148 .waitForTotalOrder(totalOrderRollbackToSavepoint, false)) 2149 loadBalancer 2150 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderRollbackToSavepoint); 2151 2152 throw e; 2153 } 2154 catch (AllBackendsFailedException e) 2155 { 2156 String msg = Translate.get( 2157 "requestmanager.rollbackavepoint.failed.all", new String []{ 2158 String.valueOf(transactionId), savepointName, e.getMessage()}); 2159 logger.error(msg); 2160 throw new SQLException (msg); 2161 } 2162 finally 2163 { 2164 if (rollbackScheduled) 2165 { 2166 scheduler.savepointCompleted(transactionId); 2168 } 2169 2170 if (validSavepoint) 2171 removeSavepoints(tid, savepointName); 2173 } 2174 } 2175 catch (RuntimeException e) 2176 { 2177 String msg = Translate 2178 .get("fatal.runtime.exception.requestmanager.rollbacksavepoint"); 2179 logger.fatal(msg, e); 2180 endUserLogger.fatal(msg); 2181 throw new SQLException (e.getMessage()); 2182 } 2183 } 2184 2185 2192 public int setSavepoint(long transactionId) throws SQLException 2193 { 2194 long startTime = System.currentTimeMillis(); 2195 try 2196 { 2197 Long tid = new Long (transactionId); 2198 TransactionMetaData tm = getTransactionMetaData(tid); 2199 String savepointName = "unnamed savepoint"; 2200 int savepointId; 2201 2202 boolean setSavepointScheduled = false; 2203 try 2204 { 2205 savepointId = scheduler.setSavepoint(tm); 2207 setSavepointScheduled = true; 2208 2209 savepointName = String.valueOf(savepointId); 2210 2211 if (logger.isDebugEnabled()) 2212 logger.debug(Translate.get("transaction.setsavepoint", new String []{ 2213 savepointName, String.valueOf(transactionId)})); 2214 2215 loadBalancer.setSavepoint(tm, savepointName); 2217 2218 if (recoveryLog != null) 2220 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2221 .currentTimeMillis() 2222 - startTime); 2223 } 2224 catch (AllBackendsFailedException e) 2225 { 2226 String msg = Translate.get("requestmanager.setsavepoint.failed.all", 2227 new String []{savepointName, String.valueOf(transactionId), 2228 e.getMessage()}); 2229 logger.error(msg); 2230 throw new SQLException (msg); 2231 } 2232 catch (SQLException e) 2233 { 2234 throw e; 2235 } 2236 finally 2237 { 2238 if (setSavepointScheduled) 2239 { 2240 scheduler.savepointCompleted(transactionId); 2242 } 2243 } 2244 2245 addSavepoint(tid, savepointName); 2247 return savepointId; 2248 } 2249 catch (RuntimeException e) 2250 { 2251 String msg = Translate 2252 .get("fatal.runtime.exception.requestmanager.setsavepoint"); 2253 logger.fatal(msg, e); 2254 endUserLogger.fatal(msg); 2255 throw new SQLException (e.getMessage()); 2256 } 2257 } 2258 2259 2266 public void setSavepoint(long transactionId, String name) throws SQLException 2267 { 2268 long startTime = System.currentTimeMillis(); 2269 try 2270 { 2271 Long tid = new Long (transactionId); 2272 TransactionMetaData tm = getTransactionMetaData(tid); 2273 2274 boolean setSavepointScheduled = false; 2275 try 2276 { 2277 scheduler.setSavepoint(tm, name, null); 2279 setSavepointScheduled = true; 2280 2281 if (logger.isDebugEnabled()) 2282 logger.debug(Translate.get("transaction.setsavepoint", new String []{ 2283 name, String.valueOf(transactionId)})); 2284 2285 loadBalancer.setSavepoint(tm, name); 2287 2288 if (recoveryLog != null) 2290 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2291 .currentTimeMillis() 2292 - startTime); 2293 } 2294 catch (AllBackendsFailedException e) 2295 { 2296 String msg = Translate.get("requestmanager.setsavepoint.failed.all", 2297 new String []{name, String.valueOf(transactionId), e.getMessage()}); 2298 logger.error(msg); 2299 throw new SQLException (msg); 2300 } 2301 catch (SQLException e) 2302 { 2303 2307 DistributedSetSavepoint totalOrderSavePoint = new DistributedSetSavepoint( 2308 tm.getLogin(), transactionId, name); 2309 if (loadBalancer.waitForTotalOrder(totalOrderSavePoint, false)) 2310 loadBalancer 2311 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderSavePoint); 2312 2313 throw e; 2314 } 2315 finally 2316 { 2317 if (setSavepointScheduled) 2318 { 2319 scheduler.savepointCompleted(transactionId); 2321 } 2322 } 2323 2324 addSavepoint(tid, name); 2326 } 2327 catch (RuntimeException e) 2328 { 2329 String msg = Translate 2330 .get("fatal.runtime.exception.requestmanager.setsavepoint"); 2331 logger.fatal(msg, e); 2332 endUserLogger.fatal(msg); 2333 throw new SQLException (e.getMessage()); 2334 } 2335 } 2336 2337 2344 public void releaseSavepoint(long transactionId, String name) 2345 throws SQLException 2346 { 2347 long startTime = System.currentTimeMillis(); 2348 try 2349 { 2350 Long tid = new Long (transactionId); 2351 TransactionMetaData tm = getTransactionMetaData(tid); 2352 2353 boolean releasedSavepointScheduled = false; 2354 try 2355 { 2356 if (!hasSavepoint(tid, name)) 2358 throw new SQLException (Translate.get( 2359 "transaction.savepoint.not.found", new String []{name, 2360 String.valueOf(transactionId)})); 2361 2362 scheduler.releaseSavepoint(tm, name, null); 2364 releasedSavepointScheduled = true; 2365 2366 if (logger.isDebugEnabled()) 2367 logger.debug(Translate.get("transaction.releasesavepoint", 2368 new String []{name, String.valueOf(transactionId)})); 2369 2370 loadBalancer.releaseSavepoint(tm, name); 2372 2373 if (recoveryLog != null) 2375 recoveryLog.logRequestCompletion(tm.getLogId(), true, System 2376 .currentTimeMillis() 2377 - startTime); 2378 } 2379 catch (SQLException e) 2380 { 2381 2385 DistributedReleaseSavepoint totalOrderReleaseSavepoint = new DistributedReleaseSavepoint( 2386 transactionId, name); 2387 if (loadBalancer.waitForTotalOrder(totalOrderReleaseSavepoint, false)) 2388 loadBalancer 2389 .removeObjectFromAndNotifyTotalOrderQueue(totalOrderReleaseSavepoint); 2390 2391 throw e; 2392 } 2393 catch (AllBackendsFailedException e) 2394 { 2395 String msg = Translate.get( 2396 "requestmanager.releasesavepoint.failed.all", new String []{name, 2397 String.valueOf(transactionId), e.getMessage()}); 2398 logger.error(msg); 2399 throw new SQLException (msg); 2400 } 2401 finally 2402 { 2403 if (releasedSavepointScheduled) 2404 { 2405 scheduler.savepointCompleted(transactionId); 2407 } 2408 2409 removeSavepoint(tid, name); 2412 } 2413 } 2414 catch (RuntimeException e) 2415 { 2416 String msg = Translate 2417 .get("fatal.runtime.exception.requestmanager.releasesavepoint"); 2418 logger.fatal(msg, e); 2419 endUserLogger.fatal(msg); 2420 throw new SQLException (e.getMessage()); 2421 } 2422 } 2423 2424 2430 public void addSavepoint(Long tid, String savepointName) 2431 { 2432 LinkedList savepoints = (LinkedList ) tidSavepoints.get(tid); 2433 if (savepoints == null) 2434 { savepoints = new LinkedList (); 2436 tidSavepoints.put(tid, savepoints); 2437 } 2438 2439 savepoints.addLast(savepointName); 2440 } 2441 2442 2448 public void removeSavepoint(Long tid, String savepointName) 2449 { 2450 LinkedList savepoints = (LinkedList ) tidSavepoints.get(tid); 2451 if (savepoints == null) 2452 logger.error("No savepoints found for transaction " + tid); 2453 else 2454 savepoints.remove(savepointName); 2455 } 2456 2457 2464 public void removeSavepoints(Long tid, String savepointName) 2465 { 2466 LinkedList savepoints = (LinkedList ) tidSavepoints.get(tid); 2467 if (savepoints == null) 2468 { 2469 logger.error("No savepoints found for transaction " + tid); 2470 return; 2471 } 2472 2473 int index = savepoints.indexOf(savepointName); 2474 if (index == -1) 2475 logger.error("No savepoint with name " + savepointName + " found " 2476 + "for transaction " + tid); 2477 else if (index < savepoints.size()) 2478 savepoints.subList(index + 1, savepoints.size()).clear(); 2479 } 2480 2481 2488 public boolean hasSavepoint(Long tid, String savepointName) 2489 { 2490 LinkedList savepoints = (LinkedList ) tidSavepoints.get(tid); 2491 if (savepoints == null) 2492 return false; 2493 2494 return savepoints.contains(savepointName); 2495 } 2496 2497 2501 2512 public void enableBackend(DatabaseBackend db) throws SQLException 2513 { 2514 loadBalancer.enableBackend(db, true); 2515 logger.info(Translate.get("backend.state.enabled", db.getName())); 2516 } 2517 2518 2535 public RecoverThread enableBackendFromCheckpoint(DatabaseBackend db, 2536 String checkpointName) throws SQLException 2537 { 2538 if (recoveryLog == null) 2540 { 2541 String msg = Translate.get( 2542 "recovery.restore.checkpoint.failed.cause.null", checkpointName); 2543 logger.error(msg); 2544 throw new SQLException (msg); 2545 } 2546 2547 if (db.getStateValue() != BackendState.DISABLED) 2548 throw new SQLException (Translate.get( 2549 "recovery.restore.backend.state.invalid", db.getName())); 2550 2551 RecoverThread recoverThread = new RecoverThread(scheduler, recoveryLog, db, 2552 this, checkpointName); 2553 2554 recoverThread.start(); 2557 return recoverThread; 2558 } 2559 2560 2571 public void disableBackend(DatabaseBackend db, boolean forceDisable) 2572 throws SQLException 2573 { 2574 if (db.isReadEnabled() || db.isWriteEnabled()) 2575 { 2576 loadBalancer.disableBackend(db, forceDisable); 2577 logger.info(Translate.get("backend.state.disabled", db.getName())); 2578 } 2579 else 2580 { 2581 throw new SQLException (Translate.get("backend.already.disabled", db 2582 .getName())); 2583 } 2584 } 2585 2586 2597 public void disableBackendWithCheckpoint(DatabaseBackend db, 2598 String checkpointName) throws SQLException 2599 { 2600 ArrayList backendsArrayList = new ArrayList (); 2601 backendsArrayList.add(new BackendInfo(db)); 2602 disableBackendsWithCheckpoint(backendsArrayList, checkpointName); 2603 } 2604 2605 2615 public void disableBackendsWithCheckpoint( 2616 final ArrayList backendInfos, String checkpointName) 2617 throws SQLException 2618 { 2619 if (recoveryLog == null) 2621 { 2622 String msg = Translate.get("recovery.store.checkpoint.failed.cause.null", 2623 checkpointName); 2624 logger.error(msg); 2625 throw new SQLException (msg); 2626 } 2627 2628 logger.info(Translate.get("requestmanager.wait.pending.writes")); 2630 scheduler.suspendNewWrites(); 2631 scheduler.waitForSuspendedWritesToComplete(); 2632 2633 recoveryLog.storeCheckpoint(checkpointName); 2635 logger.info(Translate.get("recovery.checkpoint.stored", checkpointName)); 2636 2637 List backendsToDisable = new ArrayList (); 2639 Iterator iter = backendInfos.iterator(); 2640 while (iter.hasNext()) 2641 { 2642 BackendInfo backendInfo = (BackendInfo) iter.next(); 2643 DatabaseBackend db; 2644 try 2645 { 2646 db = vdb.getAndCheckBackend(backendInfo.getName(), 2647 VirtualDatabase.NO_CHECK_BACKEND); 2648 if (db.isWriteEnabled()) 2649 { 2650 backendsToDisable.add(db); 2651 } 2652 } 2653 catch (VirtualDatabaseException e) 2654 { 2655 if (logger.isWarnEnabled()) 2656 { 2657 logger.warn(e.getMessage(), e); 2658 } 2659 } 2660 } 2661 2662 int size = backendsToDisable.size(); 2664 for (int i = 0; i < size; i++) 2665 { 2666 DatabaseBackend db = (DatabaseBackend) backendsToDisable.get(i); 2667 db.setState(BackendState.DISABLING); 2668 logger.info(Translate.get("backend.state.disabling", db.getName())); 2669 } 2670 2671 logger.info(Translate.get("requestmanager.resume.pending.writes")); 2673 scheduler.resumeWrites(); 2674 2675 for (int i = 0; i < size; i++) 2677 { 2678 DatabaseBackend db = (DatabaseBackend) backendsToDisable.get(i); 2679 db.waitForAllTransactionsAndPersistentConnectionsToComplete(); 2680 } 2681 2682 for (int i = 0; i < size; i++) 2684 { 2685 DatabaseBackend db = (DatabaseBackend) backendsToDisable.get(i); 2686 db.setLastKnownCheckpoint(checkpointName); 2687 loadBalancer.disableBackend(db, true); 2688 logger.info(Translate.get("backend.state.disabled", db.getName())); 2689 } 2690 } 2691 2692 2706 public void backupBackend(DatabaseBackend backend, String login, 2707 String password, String dumpName, String backuperName, String path, 2708 ArrayList tables) throws SQLException 2709 { 2710 Backuper backuper = backupManager.getBackuperByName(backuperName); 2711 if (backuper == null) 2712 throw new SQLException ("No backuper named " + backuperName 2713 + " was found."); 2714 2715 boolean enableAfter = false; 2716 String checkpointName = vdb.buildCheckpointName("backup " + dumpName); 2717 if (backend.isReadEnabled() || backend.isWriteEnabled()) 2718 { disableBackendWithCheckpoint(backend, checkpointName); 2720 logger.info(Translate.get("backend.state.disabled", backend.getName())); 2721 enableAfter = true; 2722 } 2723 else 2724 { 2725 if (backend.getLastKnownCheckpoint() == null) 2726 { 2727 throw new SQLException (Translate.get( 2728 "controller.backup.no.lastknown.checkpoint", backend.getName())); 2729 } 2730 } 2731 2734 try 2735 { 2736 logger.info(Translate.get("controller.backup.start", backend.getName())); 2737 2738 Vector pending = backend.getPendingRequests(); 2741 if (pending.size() != 0) 2742 { 2743 if (logger.isDebugEnabled()) 2744 { 2745 int shortFormLength = this.getVirtualDatabase() 2746 .getSqlShortFormLength(); 2747 for (int i = 0; i < pending.size(); i++) 2748 logger.debug("Pending:" 2749 + ((AbstractRequest) pending.get(i)) 2750 .toStringShortForm(shortFormLength)); 2751 2752 logger.debug("Pending Requests:" 2753 + backend.getPendingRequests().size()); 2754 logger.debug("Read enabled:" + backend.isReadEnabled()); 2755 logger.debug("Write enabled:" + backend.isWriteEnabled()); 2756 } 2757 throw new BackupException(Translate.get("backend.not.ready.for.backup")); 2758 } 2759 2760 backend.setState(BackendState.BACKUPING); 2762 Date dumpDate = backuper.backup(backend, login, password, dumpName, path, 2763 tables); 2764 if (recoveryLog != null) 2765 { 2766 DumpInfo dump = new DumpInfo(dumpName, dumpDate, path, backuper 2767 .getDumpFormat(), backend.getLastKnownCheckpoint(), backend 2768 .getName(), "*"); 2769 recoveryLog.storeDump(dump); 2770 } 2771 2772 backend.notifyJmx(SequoiaNotificationList.VIRTUALDATABASE_NEW_DUMP_LIST); 2774 } 2775 catch (BackupException be) 2776 { 2777 logger.error(Translate.get("controller.backup.failed"), be); 2778 throw new SQLException (be.getMessage()); 2779 } 2780 catch (RuntimeException e) 2781 { 2782 logger.error(Translate.get("controller.backup.failed"), e); 2783 throw new SQLException (e.getMessage()); 2784 } 2785 finally 2786 { 2787 backend.setState(BackendState.DISABLED); 2789 } 2790 2791 logger.info(Translate.get("controller.backup.complete", backend.getName())); 2792 2793 if (enableAfter) 2794 { 2795 RecoverThread thread = enableBackendFromCheckpoint(backend, 2796 checkpointName); 2797 try 2798 { 2799 thread.join(); 2800 } 2801 catch (InterruptedException e) 2802 { 2803 logger.error("Recovery thread has been interrupted", e); 2804 } 2805 } 2806 2807 } 2808 2809 2827 public void restoreBackendFromBackupCheckpoint(DatabaseBackend backend, 2828 String login, String password, String dumpName, ArrayList tables) 2829 throws BackupException 2830 { 2831 DumpInfo dumpInfo; 2832 try 2833 { 2834 dumpInfo = recoveryLog.getDumpInfo(dumpName); 2835 } 2836 catch (SQLException e) 2837 { 2838 throw new BackupException( 2839 "Recovery log error access occured while retrieving information for dump " 2840 + dumpName, e); 2841 } 2842 if (dumpInfo == null) 2843 throw new BackupException( 2844 "No information was found in the dump table for dump " + dumpName); 2845 2846 Backuper backuper = backupManager.getBackuperByFormat(dumpInfo 2847 .getDumpFormat()); 2848 if (backuper == null) 2849 throw new BackupException("No backuper was found to handle dump format " 2850 + dumpInfo.getDumpFormat()); 2851 2852 if (backend.isReadEnabled()) 2853 throw new BackupException( 2854 "Unable to restore a dump on an active backend. Disable the backend first."); 2855 2856 try 2857 { 2858 backend.setState(BackendState.RESTORING); 2859 2860 backuper.restore(backend, login, password, dumpName, dumpInfo 2861 .getDumpPath(), tables); 2862 2863 backend.setLastKnownCheckpoint(dumpInfo.getCheckpointName()); 2865 backend.setState(BackendState.DISABLED); 2866 } 2867 catch (BackupException be) 2868 { 2869 backend.setState(BackendState.UNKNOWN); 2870 logger.error(Translate.get("controller.backup.recovery.failed"), be); 2871 throw be; 2872 } 2873 finally 2874 { 2875 logger.info(Translate.get("controller.backup.recovery.done", backend 2876 .getName())); 2877 } 2878 } 2879 2880 2886 public void storeBackendsInfo(String databaseName, ArrayList backends) 2887 { 2888 if (recoveryLog == null) 2889 return; 2890 int size = backends.size(); 2891 DatabaseBackend backend; 2892 for (int i = 0; i < size; i++) 2893 { 2894 backend = (DatabaseBackend) backends.get(i); 2895 try 2896 { 2897 recoveryLog.storeBackendRecoveryInfo(databaseName, 2898 new BackendRecoveryInfo(backend.getName(), backend 2899 .getLastKnownCheckpoint(), backend.getStateValue(), 2900 databaseName)); 2901 } 2902 catch (SQLException e) 2903 { 2904 logger.error(Translate.get("recovery.store.checkpoint.failed", 2905 new String []{backend.getName(), e.getMessage()}), e); 2906 } 2907 } 2908 } 2909 2910 2915 public void removeCheckpoint(String checkpointName) 2916 { 2917 recoveryLog.removeCheckpoint(checkpointName); 2918 } 2919 2920 2924 2929 public synchronized DatabaseSchema getDatabaseSchema() 2930 { 2931 try 2932 { 2933 if (schemaIsDirty) 2936 { 2937 if (logger.isDebugEnabled()) 2938 logger.debug("Database schema is dirty, refreshing it"); 2939 DatabaseSchema activeSchema = vdb.getDatabaseSchemaFromActiveBackends(); 2940 if (activeSchema != null) 2941 { 2942 if (dbs == null) 2943 dbs = activeSchema; 2944 else 2945 dbs.mergeSchema(activeSchema); 2946 setSchemaIsDirty(false); 2947 } 2948 } 2949 } 2950 catch (SQLException e) 2951 { 2952 logger.error("Unable to refresh schema", e); 2953 } 2954 return dbs; 2955 } 2956 2957 2962 public synchronized void mergeDatabaseSchema(DatabaseSchema backendSchema) 2963 { 2964 try 2965 { 2966 if (dbs == null) 2967 setDatabaseSchema(new DatabaseSchema(backendSchema)); 2968 else 2969 { 2970 dbs.mergeSchema(backendSchema); 2971 logger.info(Translate 2972 .get("requestmanager.schema.virtualdatabase.merged.new")); 2973 2974 if (schedulerParsingranularity != ParsingGranularities.NO_PARSING) 2975 scheduler.mergeDatabaseSchema(dbs); 2976 2977 if (cacheParsingranularity != ParsingGranularities.NO_PARSING) 2978 resultCache.mergeDatabaseSchema(dbs); 2979 } 2980 } 2981 catch (SQLException e) 2982 { 2983 logger.error(Translate.get("requestmanager.schema.merge.failed", e 2984 .getMessage()), e); 2985 } 2986 } 2987 2988 2994 public synchronized void setDatabaseSchema(DatabaseSchema schema) 2995 { 2996 this.dbs = schema; 2997 logger.info(Translate.get("requestmanager.schema.set.new.virtualdatabase")); 2998 2999 if (schedulerParsingranularity != ParsingGranularities.NO_PARSING) 3000 scheduler.setDatabaseSchema(dbs); 3001 3002 if (cacheParsingranularity != ParsingGranularities.NO_PARSING) 3003 resultCache.setDatabaseSchema(dbs); 3004 3005 } 3007 3008 3013 public synchronized void setSchemaIsDirty(boolean schemaIsDirty) 3014 { 3015 this.schemaIsDirty = schemaIsDirty; 3016 } 3017 3018 3022 3027 public VirtualDatabase getVirtualDatabase() 3028 { 3029 return vdb; 3030 } 3031 3032 3037 public void setBackupManager(BackupManager currentBackupManager) 3038 { 3039 this.backupManager = currentBackupManager; 3040 } 3041 3042 3047 public BackupManager getBackupManager() 3048 { 3049 return backupManager; 3050 } 3051 3052 3057 public AbstractLoadBalancer getLoadBalancer() 3058 { 3059 return loadBalancer; 3060 } 3061 3062 3067 public void setLoadBalancer(AbstractLoadBalancer loadBalancer) 3068 { 3069 if (this.loadBalancer != null) 3070 throw new RuntimeException ( 3071 "It is not possible to dynamically change a load balancer."); 3072 this.loadBalancer = loadBalancer; 3073 if (loadBalancer == null) 3074 return; 3075 loadBalancerParsingranularity = loadBalancer.getParsingGranularity(); 3076 if (loadBalancerParsingranularity > requiredParsingGranularity) 3077 requiredParsingGranularity = loadBalancerParsingranularity; 3078 3079 try 3080 { 3081 MBeanServerManager.registerMBean(new LoadBalancerControl(loadBalancer), 3082 JmxConstants.getLoadBalancerObjectName(vdb.getVirtualDatabaseName())); 3083 } 3084 catch (Exception e) 3085 { 3086 logger.error(Translate.get("jmx.failed.register.mbean.loadbalancer")); 3087 } 3088 } 3089 3090 3096 public AbstractResultCache getResultCache() 3097 { 3098 return resultCache; 3099 } 3100 3101 3106 public MetadataCache getMetadataCache() 3107 { 3108 return metadataCache; 3109 } 3110 3111 3116 public void setMetadataCache(MetadataCache metadataCache) 3117 { 3118 this.metadataCache = metadataCache; 3119 } 3120 3121 3126 public void setParsingCache(ParsingCache parsingCache) 3127 { 3128 parsingCache.setRequestManager(this); 3129 parsingCache.setGranularity(requiredParsingGranularity); 3130 parsingCache.setCaseSensitiveParsing(isCaseSensitiveParsing); 3131 this.parsingCache = parsingCache; 3132 } 3133 3134 3139 public RecoveryLog getRecoveryLog() 3140 { 3141 return recoveryLog; 3142 } 3143 3144 3149 public void setRecoveryLog(RecoveryLog recoveryLog) 3150 { 3151 if (recoveryLog == null) 3152 return; 3153 this.recoveryLog = recoveryLog; 3154 loadBalancer.setRecoveryLog(recoveryLog); 3155 ArrayList backends = vdb.getBackends(); 3156 int size = backends.size(); 3157 backendStateListener = new BackendStateListener(vdb 3158 .getVirtualDatabaseName(), recoveryLog); 3159 for (int i = 0; i < size; i++) 3160 ((DatabaseBackend) backends.get(i)) 3161 .setStateListener(backendStateListener); 3162 } 3163 3164 3169 public void setResultCache(AbstractResultCache cache) 3170 { 3171 resultCache = cache; 3172 cacheParsingranularity = cache.getParsingGranularity(); 3173 if (cacheParsingranularity > requiredParsingGranularity) 3174 requiredParsingGranularity = cacheParsingranularity; 3175 } 3176 3177 3183 public AbstractScheduler getScheduler() 3184 { 3185 return scheduler; 3186 } 3187 3188 3193 public void setScheduler(AbstractScheduler scheduler) 3194 { 3195 this.scheduler = scheduler; 3196 schedulerParsingranularity = scheduler.getParsingGranularity(); 3197 if (schedulerParsingranularity > requiredParsingGranularity) 3198 requiredParsingGranularity = schedulerParsingranularity; 3199 } 3200 3201 3208 public void setCaseSensitiveParsing(boolean isCaseSensitiveParsing) 3209 { 3210 this.isCaseSensitiveParsing = isCaseSensitiveParsing; 3211 if (parsingCache != null) 3212 parsingCache.setCaseSensitiveParsing(isCaseSensitiveParsing); 3213 } 3214 3215 3219 3224 public String getXml() 3225 { 3226 StringBuffer info = new StringBuffer (); 3227 info.append("<" + DatabasesXmlTags.ELT_RequestManager + " " 3228 + DatabasesXmlTags.ATT_caseSensitiveParsing + "=\"" 3229 + isCaseSensitiveParsing + "\" " + DatabasesXmlTags.ATT_beginTimeout 3230 + "=\"" + beginTimeout / 1000 + "\" " 3231 + DatabasesXmlTags.ATT_commitTimeout + "=\"" + commitTimeout / 1000 3232 + "\" " + DatabasesXmlTags.ATT_rollbackTimeout + "=\"" 3233 + rollbackTimeout / 1000 + "\">"); 3234 if (scheduler != null) 3235 info.append(scheduler.getXml()); 3236 3237 if (metadataCache != null || parsingCache != null || resultCache != null) 3238 { 3239 info.append("<" + DatabasesXmlTags.ELT_RequestCache + ">"); 3240 if (metadataCache != null) 3241 info.append(metadataCache.getXml()); 3242 if (parsingCache != null) 3243 info.append(parsingCache.getXml()); 3244 if (resultCache != null) 3245 info.append(resultCache.getXml()); 3246 info.append("</" + DatabasesXmlTags.ELT_RequestCache + ">"); 3247 } 3248 3249 if (loadBalancer != null) 3250 info.append(loadBalancer.getXml()); 3251 if (recoveryLog != null) 3252 info.append(this.recoveryLog.getXml()); 3253 info.append("</" + DatabasesXmlTags.ELT_RequestManager + ">"); 3254 return info.toString(); 3255 } 3256 3257 3262 public BackendStateListener getBackendStateListener() 3263 { 3264 return backendStateListener; 3265 } 3266 3267 3272 public long getBeginTimeout() 3273 { 3274 return beginTimeout; 3275 } 3276 3277 3282 public int getCacheParsingranularity() 3283 { 3284 return cacheParsingranularity; 3285 } 3286 3287 3292 public void setCacheParsingranularity(int cacheParsingranularity) 3293 { 3294 this.cacheParsingranularity = cacheParsingranularity; 3295 } 3296 3297 3302 public long getCommitTimeout() 3303 { 3304 return commitTimeout; 3305 } 3306 3307 3314 public int getNumberOfSavepointsInTransaction(long tId) 3315 { 3316 LinkedList savepoints = (LinkedList ) tidSavepoints.get(new Long (tId)); 3317 if (savepoints == null) 3318 { 3319 return 0; 3320 } 3321 else 3322 return savepoints.size(); 3323 } 3324 3325 3330 public int getRequiredParsingGranularity() 3331 { 3332 return requiredParsingGranularity; 3333 } 3334 3335 3340 public long getRollbackTimeout() 3341 { 3342 return rollbackTimeout; 3343 } 3344 3345 3350 public int getSchedulerParsingranularity() 3351 { 3352 return schedulerParsingranularity; 3353 } 3354 3355 3360 public void setSchedulerParsingranularity(int schedulerParsingranularity) 3361 { 3362 this.schedulerParsingranularity = schedulerParsingranularity; 3363 } 3364 3365 3370 public boolean isCaseSensitiveParsing() 3371 { 3372 return isCaseSensitiveParsing; 3373 } 3374 3375 3378 public String getAssociatedString() 3379 { 3380 return "requestmanager"; 3381 } 3382 3383 3386 public void resumeActivity() 3387 { 3388 scheduler.resumeWrites(); 3389 scheduler.resumeNewTransactions(); 3390 scheduler.resumeOpenClosePersistentConnection(); 3391 } 3392 3393 3399 public void suspendActivity() throws SQLException 3400 { 3401 scheduler.suspendOpenClosePersistentConnection(); 3403 3404 scheduler.suspendNewTransactions(); 3406 3407 scheduler.suspendNewWrites(); 3409 3410 scheduler.waitForSuspendedTransactionsToComplete(); 3412 scheduler.waitForSuspendedWritesToComplete(); 3413 scheduler.waitForPendingOpenClosePersistentConnection(); 3414 } 3415 3416 3422 public String parseSqlRequest(String sqlRequest, String lineSeparator) 3423 { 3424 RequestFactory requestFactory = ControllerConstants.CONTROLLER_FACTORY 3425 .getRequestFactory(); 3426 AbstractRequest request = requestFactory.requestFromString(sqlRequest, 3427 false, false, 0, lineSeparator); 3428 try 3429 { 3430 SemanticManager semanticManager = vdb.getSemanticManager(); 3432 request.setSemanticManager(semanticManager); 3433 SemanticBehavior semantic = semanticManager.getRequestSemantic(request); 3434 3435 if (semantic != null) 3436 request.setSemantic(semantic); 3437 else 3438 { request.parse(getDatabaseSchema(), ParsingGranularities.TABLE, 3440 isCaseSensitiveParsing); 3441 } 3442 } 3443 catch (SQLException ignored) 3444 { 3445 } 3446 return request.getParsingResultsAsString(); 3447 } 3448 3449 3455 public void flushMetadataCacheAndUpdateTransactionMetadata( 3456 TransactionMetaData tm) 3457 { 3458 if (metadataCache != null) 3459 { 3460 if (tm != null) 3461 tm.setAltersMetadataCache(true); 3462 3463 metadataCache.flushCache(); 3464 } 3465 } 3466 3467 3475 public void flushAllCachesAndUpdateTransactionMetadata(TransactionMetaData tm) 3476 { 3477 if (resultCache != null) 3478 { 3479 if (tm != null) 3480 tm.setAltersQueryResultCache(true); 3481 resultCache.flushCache(); 3482 } 3483 3484 if (tm != null) 3485 tm.setAltersDatabaseSchema(true); 3486 3487 flushMetadataCacheAndUpdateTransactionMetadata(tm); 3488 } 3489} | Popular Tags |