1 24 25 package org.objectweb.cjdbc.controller.virtualdatabase; 26 27 import java.sql.SQLException ; 28 import java.util.ArrayList ; 29 import java.util.Date ; 30 import java.util.Hashtable ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.Map ; 34 35 import javax.management.NotCompliantMBeanException ; 36 import javax.management.ObjectName ; 37 38 import org.objectweb.cjdbc.common.exceptions.BackupException; 39 import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException; 40 import org.objectweb.cjdbc.common.i18n.Translate; 41 import org.objectweb.cjdbc.common.jmx.JmxConstants; 42 import org.objectweb.cjdbc.common.jmx.JmxException; 43 import org.objectweb.cjdbc.common.jmx.mbeans.VirtualDatabaseMBean; 44 import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList; 45 import org.objectweb.cjdbc.common.log.Trace; 46 import org.objectweb.cjdbc.common.monitor.backend.BackendStatistics; 47 import org.objectweb.cjdbc.common.shared.BackendInfo; 48 import org.objectweb.cjdbc.common.shared.BackendState; 49 import org.objectweb.cjdbc.common.shared.DumpInfo; 50 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest; 51 import org.objectweb.cjdbc.common.sql.SelectRequest; 52 import org.objectweb.cjdbc.common.sql.StoredProcedure; 53 import org.objectweb.cjdbc.common.sql.filters.AbstractBlobFilter; 54 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema; 55 import org.objectweb.cjdbc.common.users.AdminUser; 56 import org.objectweb.cjdbc.common.users.VirtualDatabaseUser; 57 import org.objectweb.cjdbc.common.util.Constants; 58 import org.objectweb.cjdbc.common.util.ReadPrioritaryFIFOWriteLock; 59 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags; 60 import org.objectweb.cjdbc.common.xml.XmlComponent; 61 import org.objectweb.cjdbc.common.xml.XmlTools; 62 import org.objectweb.cjdbc.controller.authentication.AuthenticationManager; 63 import org.objectweb.cjdbc.controller.backend.DatabaseBackend; 64 import org.objectweb.cjdbc.controller.backup.Backuper; 65 import org.objectweb.cjdbc.controller.cache.result.AbstractResultCache; 66 import org.objectweb.cjdbc.controller.core.Controller; 67 import org.objectweb.cjdbc.controller.core.shutdown.VirtualDatabaseForceShutdownThread; 68 import org.objectweb.cjdbc.controller.core.shutdown.VirtualDatabaseSafeShutdownThread; 69 import org.objectweb.cjdbc.controller.core.shutdown.VirtualDatabaseShutdownThread; 70 import org.objectweb.cjdbc.controller.core.shutdown.VirtualDatabaseWaitShutdownThread; 71 import org.objectweb.cjdbc.controller.jmx.AbstractStandardMBean; 72 import org.objectweb.cjdbc.controller.jmx.MBeanServerManager; 73 import org.objectweb.cjdbc.controller.jmx.RmiConnector; 74 import org.objectweb.cjdbc.controller.loadbalancer.AllBackendsFailedException; 75 import org.objectweb.cjdbc.controller.monitoring.SQLMonitoring; 76 import org.objectweb.cjdbc.controller.recoverylog.BackendRecoveryInfo; 77 import org.objectweb.cjdbc.controller.recoverylog.RecoverThread; 78 import org.objectweb.cjdbc.controller.recoverylog.RecoveryLog; 79 import org.objectweb.cjdbc.controller.requestmanager.RAIDbLevels; 80 import org.objectweb.cjdbc.controller.requestmanager.RequestManager; 81 82 96 public class VirtualDatabase extends AbstractStandardMBean 97 implements 98 VirtualDatabaseMBean, 99 XmlComponent 100 { 101 private static final long serialVersionUID = 1399418136380336827L; 102 103 116 117 protected String name; 118 119 123 protected AuthenticationManager authenticationManager; 124 125 126 protected ArrayList backends; 127 128 129 protected ReadPrioritaryFIFOWriteLock rwLock; 130 131 132 protected RequestManager requestManager; 133 134 135 protected LinkedList totalOrderQueue = null; 136 137 138 public Trace logger = null; 139 protected Trace requestLogger = null; 140 141 private ArrayList activeThreads = new ArrayList (); 143 private int idleThreads = 0; 145 private ArrayList pendingConnections = new ArrayList (); 147 148 149 protected int maxNbOfConnections; 150 151 152 protected boolean poolConnectionThreads; 153 154 155 protected long maxThreadIdleTime; 156 157 161 protected int minNbOfThreads; 162 163 164 protected int maxNbOfThreads; 165 166 167 protected int currentNbOfThreads; 168 169 170 protected VirtualDatabaseDynamicMetaData metadata; 171 private VirtualDatabaseStaticMetaData staticMetadata; 172 173 private SQLMonitoring sqlMonitor = null; 174 175 176 public static final int CHECK_BACKEND_ENABLE = 1; 177 178 public static final int CHECK_BACKEND_DISABLE = 0; 179 180 public static final int NO_CHECK_BACKEND = -1; 181 182 183 private int sqlShortFormLength; 184 185 186 private AbstractBlobFilter blobFilter; 187 188 189 Controller controller; 190 191 192 private String databaseProductNames = "C-JDBC"; 193 194 195 private boolean shuttingDown = false; 196 197 198 199 217 public VirtualDatabase(Controller controller, String name, 218 int maxConnections, boolean pool, int minThreads, int maxThreads, 219 long maxThreadIdleTime, int sqlShortFormLength, 220 AbstractBlobFilter blobFilter) throws NotCompliantMBeanException , 221 JmxException 222 { 223 super(VirtualDatabaseMBean.class); 224 this.controller = controller; 225 this.name = name; 226 this.maxNbOfConnections = maxConnections; 227 this.poolConnectionThreads = pool; 228 this.minNbOfThreads = minThreads; 229 this.maxNbOfThreads = maxThreads; 230 this.maxThreadIdleTime = maxThreadIdleTime; 231 this.sqlShortFormLength = sqlShortFormLength; 232 this.blobFilter = blobFilter; 233 backends = new ArrayList (); 234 235 ObjectName objectName = JmxConstants.getVirtualDbObjectName(name); 236 MBeanServerManager.registerMBean(this, objectName); 237 238 rwLock = new ReadPrioritaryFIFOWriteLock(); 239 logger = Trace.getLogger("org.objectweb.cjdbc.controller.virtualdatabase." 240 + name); 241 requestLogger = Trace 242 .getLogger("org.objectweb.cjdbc.controller.virtualdatabase.request." 243 + name); 244 } 245 246 253 public final void acquireReadLockBackendLists() throws InterruptedException 254 { 255 rwLock.acquireRead(); 256 } 257 258 263 public final void releaseReadLockBackendLists() 264 { 265 rwLock.releaseRead(); 266 } 267 268 273 public boolean isDistributed() 274 { 275 return false; 276 } 277 278 279 280 289 public boolean checkUserAuthentication(String virtualLogin, 290 String virtualPassword) 291 { 292 if (authenticationManager == null) 293 { 294 logger.error("No authentification manager defined to check login '" 295 + virtualLogin + "'"); 296 return false; 297 } 298 else 299 return authenticationManager.isValidVirtualUser(new VirtualDatabaseUser( 300 virtualLogin, virtualPassword)); 301 } 302 303 312 public boolean checkAdminAuthentication(String adminLogin, 313 String adminPassword) 314 { 315 if (authenticationManager == null) 316 { 317 logger.error("No authentification manager defined to check admin login '" 318 + adminLogin + "'"); 319 return false; 320 } 321 else 322 return authenticationManager.isValidAdminUser(new AdminUser(adminLogin, 323 adminPassword)); 324 } 325 326 333 public ControllerResultSet execReadRequest(SelectRequest request) 334 throws SQLException 335 { 336 if (request == null) 337 { 338 String msg = "Request failed (null read request received)"; 339 logger.warn(msg); 340 throw new SQLException (msg); 341 } 342 343 try 344 { 345 if (requestLogger.isInfoEnabled()) 346 requestLogger.info("S " + request.getTransactionId() + " " 347 + request.getSQL()); 348 349 long start = 0; 350 if (sqlMonitor != null && sqlMonitor.isActive()) 351 start = System.currentTimeMillis(); 352 353 ControllerResultSet rs = requestManager.execReadRequest(request); 354 355 if (sqlMonitor != null && sqlMonitor.isActive()) 356 sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start); 357 358 return rs; 359 } 360 catch (SQLException e) 361 { 362 String msg = "Request '" + request.getId() + "' failed (" 363 + e.getMessage() + ")"; 364 logger.warn(msg); 365 if (sqlMonitor != null && sqlMonitor.isActive()) 366 sqlMonitor.logError(request); 367 throw e; 368 } 369 } 370 371 378 public int execWriteRequest(AbstractWriteRequest request) throws SQLException 379 { 380 if (request == null) 381 { 382 String msg = "Request failed (null write request received)"; 383 logger.warn(msg); 384 throw new SQLException (msg); 385 } 386 387 try 388 { 389 if (requestLogger.isInfoEnabled()) 390 requestLogger.info("W " + request.getTransactionId() + " " 391 + request.getSQL()); 392 393 long start = 0; 394 if (sqlMonitor != null && sqlMonitor.isActive()) 395 start = System.currentTimeMillis(); 396 397 int result = requestManager.execWriteRequest(request); 398 399 if (sqlMonitor != null && sqlMonitor.isActive()) 400 sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start); 401 402 return result; 403 } 404 catch (SQLException e) 405 { 406 String msg = "Request '" + request.getId() + "' failed (" 407 + e.getMessage() + ")"; 408 logger.warn(msg); 409 if (sqlMonitor != null && sqlMonitor.isActive()) 410 sqlMonitor.logError(request); 411 throw e; 412 } 413 } 414 415 422 public ControllerResultSet execWriteRequestWithKeys( 423 AbstractWriteRequest request) throws SQLException 424 { 425 if (request == null) 426 { 427 String msg = "Request failed (null write request received)"; 428 logger.warn(msg); 429 throw new SQLException (msg); 430 } 431 432 try 433 { 434 if (requestLogger.isInfoEnabled()) 435 requestLogger.info("W " + request.getTransactionId() + " " 436 + request.getSQL()); 437 438 long start = 0; 439 if (sqlMonitor != null && sqlMonitor.isActive()) 440 start = System.currentTimeMillis(); 441 442 ControllerResultSet result = requestManager 443 .execWriteRequestWithKeys(request); 444 445 if (sqlMonitor != null && sqlMonitor.isActive()) 446 sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start); 447 448 return result; 449 } 450 catch (SQLException e) 451 { 452 String msg = "Request '" + request.getId() + "' failed (" 453 + e.getMessage() + ")"; 454 logger.warn(msg); 455 if (sqlMonitor != null && sqlMonitor.isActive()) 456 sqlMonitor.logError(request); 457 throw e; 458 } 459 } 460 461 468 public ControllerResultSet execReadStoredProcedure(StoredProcedure proc) 469 throws SQLException 470 { 471 if (proc == null) 472 { 473 String msg = "Request failed (null stored procedure received)"; 474 logger.warn(msg); 475 throw new SQLException (msg); 476 } 477 478 try 479 { 480 if (requestLogger.isInfoEnabled()) 481 requestLogger 482 .info("S " + proc.getTransactionId() + " " + proc.getSQL()); 483 484 long start = 0; 485 if (sqlMonitor != null && sqlMonitor.isActive()) 486 start = System.currentTimeMillis(); 487 488 ControllerResultSet rs = requestManager.execReadStoredProcedure(proc); 489 490 if (sqlMonitor != null && sqlMonitor.isActive()) 491 sqlMonitor.logRequestTime(proc, System.currentTimeMillis() - start); 492 493 return rs; 494 } 495 catch (AllBackendsFailedException e) 496 { 497 String msg = Translate.get( 498 "loadbalancer.storedprocedure.failed.on.all.backends", new String []{ 499 String.valueOf(proc.getId()), e.getMessage()}); 500 logger.warn(msg); 501 if (sqlMonitor != null && sqlMonitor.isActive()) 502 sqlMonitor.logError(proc); 503 throw new SQLException (msg); 504 } 505 catch (SQLException e) 506 { 507 String msg = Translate.get("loadbalancer.storedprocedure.failed", 508 new String []{String.valueOf(proc.getId()), e.getMessage()}); 509 logger.warn(msg); 510 if (sqlMonitor != null && sqlMonitor.isActive()) 511 sqlMonitor.logError(proc); 512 throw e; 513 } 514 } 515 516 523 protected int execWriteStoredProcedure(StoredProcedure proc) 524 throws SQLException 525 { 526 if (proc == null) 527 { 528 String msg = "Request failed (null stored procedure received)"; 529 logger.warn(msg); 530 throw new SQLException (msg); 531 } 532 533 try 534 { 535 if (requestLogger.isInfoEnabled()) 536 requestLogger 537 .info("W " + proc.getTransactionId() + " " + proc.getSQL()); 538 539 long start = 0; 540 if (sqlMonitor != null && sqlMonitor.isActive()) 541 start = System.currentTimeMillis(); 542 543 int result = requestManager.execWriteStoredProcedure(proc); 544 545 if (sqlMonitor != null && sqlMonitor.isActive()) 546 sqlMonitor.logRequestTime(proc, System.currentTimeMillis() - start); 547 548 return result; 549 } 550 catch (AllBackendsFailedException e) 551 { 552 String msg = Translate.get( 553 "loadbalancer.storedprocedure.failed.on.all.backends", new String []{ 554 String.valueOf(proc.getId()), e.getMessage()}); 555 logger.warn(msg); 556 if (sqlMonitor != null && sqlMonitor.isActive()) 557 sqlMonitor.logError(proc); 558 throw new SQLException (msg); 559 } 560 catch (SQLException e) 561 { 562 String msg = Translate.get("loadbalancer.storedprocedure.failed", 563 new String []{String.valueOf(proc.getId()), e.getMessage()}); 564 logger.warn(msg); 565 if (sqlMonitor != null && sqlMonitor.isActive()) 566 sqlMonitor.logError(proc); 567 throw e; 568 } 569 } 570 571 572 573 587 public long begin(String login) throws SQLException 588 { 589 try 590 { 591 long tid = requestManager.begin(login); 592 if (requestLogger.isInfoEnabled()) 593 requestLogger.info("B " + tid); 594 return tid; 595 } 596 catch (SQLException e) 597 { 598 String msg = "Begin failed (" + e.getMessage() + ")"; 599 logger.warn(msg); 600 throw e; 601 } 602 } 603 604 615 public void abort(long transactionId, boolean logAbort) throws SQLException 616 { 617 requestManager.abort(transactionId, logAbort); 618 if (requestLogger.isInfoEnabled()) 620 requestLogger.info("R " + transactionId); 621 } 622 623 630 public void commit(long transactionId, boolean logCommit) throws SQLException 631 { 632 try 633 { 634 if (requestLogger.isInfoEnabled()) 635 requestLogger.info("C " + transactionId); 636 requestManager.commit(transactionId, logCommit); 637 } 638 catch (SQLException e) 639 { 640 String msg = "Commit of transaction '" + transactionId + "' failed (" 641 + e.getMessage() + ")"; 642 logger.warn(msg); 643 throw e; 644 } 645 } 646 647 655 public void rollback(long transactionId, boolean logRollback) 656 throws SQLException 657 { 658 try 659 { 660 if (requestLogger.isInfoEnabled()) 661 requestLogger.info("R " + transactionId); 662 requestManager.rollback(transactionId, logRollback); 663 } 664 catch (SQLException e) 665 { 666 String msg = "Rollback of transaction '" + transactionId + "' failed (" 667 + e.getMessage() + ")"; 668 logger.warn(msg); 669 throw e; 670 } 671 } 672 673 680 public void rollback(long transactionId, String savepointName) 681 throws SQLException 682 { 683 try 684 { 685 if (requestLogger.isInfoEnabled()) 686 requestLogger.info("R " + transactionId + " " + savepointName); 687 requestManager.rollback(transactionId, savepointName); 688 } 689 catch (SQLException e) 690 { 691 String msg = "Rollback to savepoint '" + savepointName + "' for " 692 + "transaction '" + transactionId + "' failed (" + e.getMessage() 693 + ")"; 694 logger.warn(msg); 695 throw e; 696 } 697 } 698 699 706 public int setSavepoint(long transactionId) throws SQLException 707 { 708 try 709 { 710 int savepointId = requestManager.setSavepoint(transactionId); 711 if (requestLogger.isInfoEnabled()) 712 requestLogger.info("P " + transactionId + " " + savepointId); 713 return savepointId; 714 } 715 catch (SQLException e) 716 { 717 String msg = "Setting unnamed savepoint to transaction '" + transactionId 718 + "' failed (" + e.getMessage() + ")"; 719 logger.warn(msg); 720 throw e; 721 } 722 } 723 724 731 public void setSavepoint(long transactionId, String name) throws SQLException 732 { 733 try 734 { 735 if (requestLogger.isInfoEnabled()) 736 requestLogger.info("P " + transactionId + " " + name); 737 requestManager.setSavepoint(transactionId, name); 738 } 739 catch (SQLException e) 740 { 741 String msg = "Setting savepoint with name '" + name + "' to transaction " 742 + "'" + transactionId + "' failed (" + e.getMessage() + ")"; 743 logger.warn(msg); 744 throw e; 745 } 746 } 747 748 755 public void releaseSavepoint(long transactionId, String name) 756 throws SQLException 757 { 758 try 759 { 760 if (requestLogger.isInfoEnabled()) 761 requestLogger.info("F " + transactionId + " " + name); 762 requestManager.releaseSavepoint(transactionId, name); 763 } 764 catch (SQLException e) 765 { 766 String msg = "Releasing savepoint with name '" + name + "' from " 767 + "transaction '" + transactionId + "' failed (" + e.getMessage() 768 + ")"; 769 logger.warn(msg); 770 throw e; 771 } 772 } 773 774 778 784 public void addBackend(DatabaseBackend db) throws VirtualDatabaseException 785 { 786 this.addBackend(db, true); 787 } 788 789 796 public void addBackend(DatabaseBackend db, boolean checkForCompliance) 797 throws VirtualDatabaseException 798 { 799 if (db == null) 800 { 801 String msg = "Illegal null database backend in addBackend(DatabaseBackend) method"; 802 logger.error(msg); 803 throw new VirtualDatabaseException(msg); 804 } 805 806 if (db.isReadEnabled()) 807 { 808 String msg = "It is not allowed to add an enabled database."; 809 logger.error(msg); 810 throw new VirtualDatabaseException(msg); 811 } 812 813 try 815 { 816 rwLock.acquireWrite(); 817 } 818 catch (InterruptedException e) 819 { 820 String msg = Translate.get( 821 "loadbalancer.backendlist.acquire.writelock.failed", e); 822 logger.error(msg); 823 throw new VirtualDatabaseException(msg); 824 } 825 826 if (backends.indexOf(db) != -1) 828 { 829 rwLock.releaseWrite(); 830 String msg = "Duplicate backend " + db.getURL(); 831 logger.warn(msg); 832 throw new VirtualDatabaseException(msg); 833 } 834 835 ArrayList logins = authenticationManager.getVirtualLogins(); 837 VirtualDatabaseUser vdu; 838 String login; 839 for (int i = 0; i < logins.size(); i++) 840 { 841 vdu = (VirtualDatabaseUser) logins.get(i); 842 login = vdu.getLogin(); 843 if (db.getConnectionManager(login) == null) 844 { 845 rwLock.releaseWrite(); 846 throw new VirtualDatabaseException(Translate.get( 847 "backend.missing.connection.manager", login)); 848 } 849 } 850 851 try 853 { 854 if (logger.isDebugEnabled()) 855 logger.debug("Checking driver compliance"); 856 if (checkForCompliance) 857 db.checkDriverCompliance(); } 859 catch (Exception e) 860 { 861 rwLock.releaseWrite(); 862 String msg = "Error while adding database backend " + db.getName() + " (" 863 + e + ")"; 864 logger.warn(msg); 865 throw new VirtualDatabaseException(msg); 866 } 867 868 db.setSqlShortFormLength(getSQLShortFormLength()); 869 870 backends.add(db); 872 if (logger.isDebugEnabled()) 873 logger.debug("Backend " + db.getName() + " added successfully"); 874 875 885 if (getRequestManager() != null) 886 { 887 db.setStateListener(getRequestManager().getBackendStateListener()); 888 } 889 890 rwLock.releaseWrite(); 892 893 if (MBeanServerManager.isJmxEnabled()) 895 { 896 Hashtable data = new Hashtable (); 898 data.put(CjdbcNotificationList.DATA_DATABASE, this.name); 899 data.put(CjdbcNotificationList.DATA_DRIVER, db.getDriverClassName()); 900 String checkpoint = db.getLastKnownCheckpoint(); 901 checkpoint = (checkpoint == null) ? "" : checkpoint; 902 data.put(CjdbcNotificationList.DATA_CHECKPOINT, checkpoint); 903 data.put(CjdbcNotificationList.DATA_NAME, db.getName()); 904 data.put(CjdbcNotificationList.DATA_URL, db.getURL()); 905 RmiConnector.broadcastNotification(this, 906 CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ADDED, 907 CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get( 908 "notification.backend.added", db.getName()), data); 909 910 ObjectName objectName = JmxConstants.getDatabaseBackendObjectName(name, 912 db.getName()); 913 try 914 { 915 MBeanServerManager.registerMBean(db, objectName); 916 } 917 catch (JmxException e1) 918 { 919 logger.error(Translate.get( 920 "virtualdatabase.fail.register.backend.mbean", db.getName()), e1); 921 } 922 } 923 } 924 925 928 public void forceDisableBackend(String backendName) 929 throws VirtualDatabaseException 930 { 931 try 932 { 933 DatabaseBackend db = getAndCheckBackend(backendName, 934 CHECK_BACKEND_DISABLE); 935 requestManager.disableBackend(db); 936 requestManager.setDatabaseSchema( 937 getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames(), 938 false); 939 940 if (MBeanServerManager.isJmxEnabled()) 942 { 943 Hashtable data = new Hashtable (); 944 data.put("driver", db.getDriverClassName()); 945 String checkpoint = db.getLastKnownCheckpoint(); 946 checkpoint = (checkpoint == null) ? "" : checkpoint; 947 data.put("checkpoint", checkpoint); 948 data.put("name", db.getName()); 949 data.put("url", db.getURL()); 950 RmiConnector.broadcastNotification(this, 951 CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLED, 952 CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get( 953 "notification.backend.disabled", db.getName()), data); 954 } 955 } 956 catch (Exception e) 957 { 958 logger.error("An error occured while disabling backend " + backendName 959 + " (" + e + ")"); 960 throw new VirtualDatabaseException(e.getMessage()); 961 } 962 } 963 964 972 public void disableAllBackends() throws VirtualDatabaseException 973 { 974 try 975 { 976 int size = this.backends.size(); 977 DatabaseBackend dbe; 978 for (int i = 0; i < size; i++) 979 { 980 dbe = (DatabaseBackend) backends.get(i); 981 if (dbe.isReadEnabled()) 982 requestManager.disableBackend(getAndCheckBackend(dbe.getName(), 983 CHECK_BACKEND_DISABLE)); 984 } 985 } 986 catch (Exception e) 987 { 988 throw new VirtualDatabaseException(e.getMessage()); 989 } 990 } 991 992 995 public void disableBackendWithCheckpoint(String backendName) 996 throws VirtualDatabaseException 997 { 998 try 999 { 1000 requestManager.disableBackendForCheckpoint(getAndCheckBackend( 1001 backendName, CHECK_BACKEND_DISABLE), "disable_backend_" + backendName 1002 + "_" + new Date (System.currentTimeMillis()).toString()); 1003 requestManager.setDatabaseSchema( 1004 getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames(), 1005 false); 1006 } 1007 catch (Exception e) 1008 { 1009 logger.error("An error occured while disabling backend " + backendName 1010 + " (" + e + ")"); 1011 throw new VirtualDatabaseException(e.getMessage()); 1012 } 1013 } 1014 1015 1018 public void disableAllBackendsWithCheckpoint(String checkpoint) 1019 throws VirtualDatabaseException 1020 { 1021 if (checkpoint == null) 1022 { 1023 disableAllBackends(); 1024 return; 1025 } 1026 1027 try 1028 { 1029 this.acquireReadLockBackendLists(); 1030 requestManager.disableBackendsForCheckpoint(backends, checkpoint); 1031 this.releaseReadLockBackendLists(); 1032 } 1033 catch (Exception e) 1034 { 1035 throw new VirtualDatabaseException(e.getMessage()); 1036 } 1037 } 1038 1039 1042 public void forceEnableBackend(String backendName) 1043 throws VirtualDatabaseException 1044 { 1045 try 1047 { 1048 DatabaseBackend backend = getAndCheckBackend(backendName, 1049 CHECK_BACKEND_ENABLE); 1050 1051 requestManager.enableBackend(backend); 1052 requestManager.setSchemaIsDirty(true); 1053 1054 if (databaseProductNames.indexOf(backend.getDatabaseProductName()) == -1) 1056 databaseProductNames += "," + backend.getDatabaseProductName(); 1057 1058 getStaticMetaData().gatherStaticMetadata(backend); 1060 1061 if (MBeanServerManager.isJmxEnabled()) 1063 { 1064 Hashtable data = new Hashtable (); 1065 data.put("driver", backend.getDriverClassName()); 1066 String checkpoint = backend.getLastKnownCheckpoint(); 1067 checkpoint = (checkpoint == null) ? "" : checkpoint; 1068 data.put("checkpoint", checkpoint); 1069 data.put("name", backend.getName()); 1070 data.put("url", backend.getURL()); 1071 RmiConnector.broadcastNotification(this, 1072 CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED, 1073 CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get( 1074 "notification.backend.enabled", backend.getName()), data); 1075 } 1076 } 1077 catch (Exception e) 1078 { 1079 e.printStackTrace(); 1080 throw new VirtualDatabaseException(e.getMessage()); 1081 } 1082 } 1083 1084 1092 public void enableBackendFromCheckpoint(String backendName, 1093 String checkpointName) throws VirtualDatabaseException 1094 { 1095 try 1097 { 1098 DatabaseBackend backend = getAndCheckBackend(backendName, 1099 CHECK_BACKEND_ENABLE); 1100 RecoverThread recoverThread = requestManager.enableBackendFromCheckpoint( 1101 backend, checkpointName); 1102 recoverThread.join(); 1104 requestManager.setSchemaIsDirty(true); 1105 1106 getStaticMetaData().gatherStaticMetadata(backend); 1108 1109 if (databaseProductNames.indexOf(backend.getDatabaseProductName()) == -1) 1111 databaseProductNames += "," + backend.getDatabaseProductName(); 1112 } 1113 catch (Exception e) 1114 { 1115 throw new VirtualDatabaseException( 1116 "Failed to enable backend from checkpoint: " + e); 1117 } 1118 } 1119 1120 1123 public void enableBackendFromCheckpoint(String backendName) 1124 throws VirtualDatabaseException 1125 { 1126 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 1127 String checkpoint = backend.getLastKnownCheckpoint(); 1128 if (checkpoint == null) 1129 throw new VirtualDatabaseException("No last checkpoint for backend:" 1130 + backendName); 1131 else 1132 { 1133 if (logger.isDebugEnabled()) 1134 logger.debug("Enabling backend:" + backendName 1135 + " from its last checkpoint " + backend.getLastKnownCheckpoint()); 1136 } 1137 enableBackendFromCheckpoint(backendName, backend.getLastKnownCheckpoint()); 1138 } 1139 1140 1145 public void enableAllBackends() throws VirtualDatabaseException 1146 { 1147 try 1148 { 1149 int size = this.backends.size(); 1150 DatabaseBackend dbe; 1151 for (int i = 0; i < size; i++) 1152 { 1153 dbe = (DatabaseBackend) backends.get(i); 1154 if (!dbe.isReadEnabled()) 1155 forceEnableBackend(((DatabaseBackend) backends.get(i)).getName()); 1156 } 1157 } 1158 catch (Exception e) 1159 { 1160 logger.error(e); 1161 throw new VirtualDatabaseException(e.getMessage()); 1162 } 1163 } 1164 1165 1168 public void enableAllBackendsFromCheckpoint() throws VirtualDatabaseException 1169 { 1170 RecoveryLog log = requestManager.getRecoveryLog(); 1171 if (log == null) 1172 { logger 1174 .warn("No recovery log has been configured, enabling backend without checkpoint."); 1175 enableAllBackends(); 1176 } 1177 else 1178 { 1179 try 1180 { 1181 int size = this.backends.size(); 1182 DatabaseBackend dbe; 1183 String backendName; 1184 BackendRecoveryInfo info; 1185 for (int i = 0; i < size; i++) 1186 { 1187 dbe = (DatabaseBackend) backends.get(i); 1188 backendName = dbe.getName(); 1189 info = log.getBackendRecoveryInfo(name, backendName); 1190 switch (info.getBackendState()) 1191 { 1192 case BackendState.DISABLED : 1193 String checkpoint = info.getCheckpoint(); 1194 if (checkpoint == null || checkpoint.equals("")) 1195 { 1196 logger.warn("Enabling backend " + backendName 1197 + " with no checkpoint."); 1198 forceEnableBackend(dbe.getName()); 1199 } 1200 else 1201 { 1202 logger.info("Enabling backend " + backendName 1203 + " from checkpoint " + checkpoint); 1204 enableBackendFromCheckpoint(dbe.getName(), checkpoint); 1205 } 1206 continue; 1207 case BackendState.UNKNOWN : 1208 logger.info("Unknown last state for backend " + backendName 1209 + ". Leaving node in " 1210 + (dbe.isReadEnabled() ? "enabled" : "disabled") + " state."); 1211 continue; 1212 case BackendState.BACKUPING : 1213 case BackendState.DISABLING : 1214 case BackendState.RECOVERING : 1215 case BackendState.REPLAYING : 1216 if (!dbe.isReadEnabled()) 1217 { 1218 logger.info("Unexpected transition state (" 1219 + info.getBackendState() + ") for backend " + backendName 1220 + ". Forcing backend to disabled state."); 1221 info.setBackendState(BackendState.DISABLED); 1222 log.storeBackendRecoveryInfo(name, info); 1223 } 1224 else 1225 logger.info("Unexpected transition state (" 1226 + info.getBackendState() + ") for backend " + backendName 1227 + ". Leaving backend in its current state."); 1228 continue; 1229 default : 1230 if (!dbe.isReadEnabled()) 1231 { 1232 logger.info("Unexpected enabled state (" 1233 + info.getBackendState() + ") for backend " + backendName 1234 + ". Forcing backend to disabled state."); 1235 info.setBackendState(BackendState.DISABLED); 1236 log.storeBackendRecoveryInfo(name, info); 1237 } 1238 else 1239 logger.info("Unexpected enabled state (" 1240 + info.getBackendState() + ") for backend " + backendName 1241 + ". Leaving backend in its current state."); 1242 continue; 1243 } 1244 } 1245 } 1246 catch (Exception e) 1247 { 1248 throw new VirtualDatabaseException(e.getMessage()); 1249 } 1250 } 1251 1252 } 1253 1254 1263 public void forceEnableAllBackendsFromCheckpoint(String checkpoint) 1264 throws VirtualDatabaseException 1265 { 1266 if (checkpoint == null || checkpoint.equals("")) 1267 enableAllBackends(); 1268 else 1269 { 1270 try 1271 { 1272 int size = this.backends.size(); 1273 DatabaseBackend backend; 1274 for (int i = 0; i < size; i++) 1275 { 1276 backend = (DatabaseBackend) backends.get(i); 1277 if (!backend.isReadEnabled()) 1278 { 1279 backend.setLastKnownCheckpoint(checkpoint); 1280 enableBackendFromCheckpoint(backend.getName(), checkpoint); 1281 } 1282 } 1283 } 1284 catch (Exception e) 1285 { 1286 throw new VirtualDatabaseException(e.getMessage()); 1287 } 1288 } 1289 } 1290 1291 1294 public ArrayList getAllBackendNames() throws VirtualDatabaseException 1295 { 1296 try 1297 { 1298 acquireReadLockBackendLists(); 1299 } 1300 catch (InterruptedException e) 1301 { 1302 String msg = "Unable to acquire read lock on backend list in getAllBackendNames (" 1303 + e + ")"; 1304 logger.error(msg); 1305 throw new VirtualDatabaseException(msg); 1306 } 1307 1308 int size = backends.size(); 1309 ArrayList result = new ArrayList (); 1310 for (int i = 0; i < size; i++) 1311 { 1312 result.add(((DatabaseBackend) backends.get(i)).getName()); 1313 } 1314 1315 releaseReadLockBackendLists(); 1316 return result; 1317 } 1318 1319 1332 public DatabaseBackend getAndCheckBackend(String backendName, int testEnable) 1333 throws VirtualDatabaseException 1334 { 1335 try 1336 { 1337 acquireReadLockBackendLists(); 1338 } 1339 catch (InterruptedException e) 1340 { 1341 String msg = "Unable to acquire read lock on backend list in getAndCheckBackend (" 1342 + e + ")"; 1343 logger.error(msg); 1344 throw new VirtualDatabaseException(msg); 1345 } 1346 1347 int size = backends.size(); 1349 DatabaseBackend b = null; 1350 for (int i = 0; i < size; i++) 1351 { 1352 b = (DatabaseBackend) backends.get(i); 1353 if (b.getName().equals(backendName)) 1354 break; 1355 else 1356 b = null; 1357 } 1358 1359 if (b == null) 1361 { 1362 releaseReadLockBackendLists(); 1363 String msg = "Trying to access a non-existing backend " + backendName; 1364 logger.warn(msg); 1365 throw new VirtualDatabaseException(msg); 1366 } 1367 1368 switch (testEnable) 1370 { 1371 case NO_CHECK_BACKEND : 1372 break; 1373 case CHECK_BACKEND_DISABLE : 1374 if (!b.isReadEnabled()) 1375 { 1376 releaseReadLockBackendLists(); 1377 String msg = "Backend " + backendName + " is already disabled"; 1378 logger.warn(msg); 1379 throw new VirtualDatabaseException(msg); 1380 } 1381 break; 1382 case CHECK_BACKEND_ENABLE : 1383 if (b.isReadEnabled()) 1384 { 1385 releaseReadLockBackendLists(); 1386 String msg = "Backend " + backendName + " is already enabled"; 1387 logger.warn(msg); 1388 throw new VirtualDatabaseException(msg); 1389 } 1390 break; 1391 default : 1392 releaseReadLockBackendLists(); 1393 String msg = "Unexpected parameter in getAndCheckBackend(...)"; 1394 logger.error(msg); 1395 throw new VirtualDatabaseException(msg); 1396 } 1397 1398 releaseReadLockBackendLists(); 1399 1400 if (testEnable == CHECK_BACKEND_ENABLE) 1401 { 1402 try 1404 { 1405 if (logger.isDebugEnabled()) 1406 logger.debug("Initializing connections for backend " + b.getName()); 1407 b.initializeConnections(); 1408 1409 b.checkDriverCompliance(); 1410 1411 if (logger.isDebugEnabled()) 1412 logger.debug("Checking schema for backend " + b.getName()); 1413 b.checkDatabaseSchema(); 1414 1415 DatabaseSchema backendSchema = b.getDatabaseSchema(); 1416 1417 if (backendSchema != null) 1418 requestManager.mergeDatabaseSchema(backendSchema); 1419 else 1420 logger.warn("Backend " + b.getName() + " has no defined schema."); 1421 } 1422 catch (SQLException e) 1423 { 1424 String msg = "Error while initalizing database backend " + b.getName() 1425 + " (" + e + ")"; 1426 logger.warn(msg, e); 1427 throw new VirtualDatabaseException(msg); 1428 } 1429 } 1430 1431 return b; 1432 } 1433 1434 1438 public void replicateBackend(String backendName, String newBackendName, 1439 Map parameters) throws VirtualDatabaseException 1440 { 1441 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 1443 DatabaseBackend newBackend = null; 1444 1445 try 1447 { 1448 newBackend = backend.copy(newBackendName, parameters); 1449 } 1450 catch (Exception e) 1451 { 1452 String msg = Translate.get("virtualdatabase.fail.backend.copy"); 1453 logger.warn(msg, e); 1454 throw new VirtualDatabaseException(msg); 1455 } 1456 1457 addBackend(newBackend); 1459 } 1460 1461 1464 public void removeBackend(String backend) throws VirtualDatabaseException 1465 { 1466 removeBackend(getAndCheckBackend(backend, NO_CHECK_BACKEND)); 1467 } 1468 1469 1475 public void removeBackend(DatabaseBackend db) throws VirtualDatabaseException 1476 { 1477 if (db == null) 1478 { 1479 String msg = "Illegal null database backend in removeBackend(DatabaseBackend) method"; 1480 logger.error(msg); 1481 throw new VirtualDatabaseException(msg); 1482 } 1483 1484 try 1485 { 1486 rwLock.acquireWrite(); 1487 } 1488 catch (InterruptedException e) 1489 { 1490 String msg = Translate.get( 1491 "loadbalancer.backendlist.acquire.writelock.failed", e); 1492 logger.error(msg); 1493 throw new VirtualDatabaseException(msg); 1494 } 1495 1496 int idx = backends.indexOf(db); 1498 if (idx == -1) 1499 { 1500 rwLock.releaseWrite(); String msg = "Trying to remove a non-existing backend " + db.getName(); 1502 logger.warn(msg); 1503 throw new VirtualDatabaseException(msg); 1504 } 1505 1506 if (((DatabaseBackend) backends.get(idx)).isReadEnabled()) 1507 { 1508 rwLock.releaseWrite(); String msg = "Trying to remove an enabled backend " + db.getName(); 1510 logger.error(msg); 1511 throw new VirtualDatabaseException(msg); 1512 } 1513 1514 backends.remove(idx); 1516 rwLock.releaseWrite(); 1518 if (MBeanServerManager.isJmxEnabled()) 1520 { 1521 Hashtable data = new Hashtable (); 1523 data.put(CjdbcNotificationList.DATA_DATABASE, this.name); 1524 data.put(CjdbcNotificationList.DATA_DRIVER, db.getDriverClassName()); 1525 String checkpoint = db.getLastKnownCheckpoint(); 1526 checkpoint = (checkpoint == null) ? "" : checkpoint; 1527 data.put(CjdbcNotificationList.DATA_CHECKPOINT, checkpoint); 1528 data.put(CjdbcNotificationList.DATA_NAME, db.getName()); 1529 data.put(CjdbcNotificationList.DATA_URL, db.getURL()); 1530 RmiConnector.broadcastNotification(this, 1531 CjdbcNotificationList.VIRTUALDATABASE_BACKEND_REMOVED, 1532 CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get( 1533 "notification.backend.removed", db.getName()), data); 1534 1535 ObjectName objectName = JmxConstants.getDatabaseBackendObjectName(name, 1537 db.getName()); 1538 try 1539 { 1540 MBeanServerManager.unregister(objectName); 1541 } 1542 catch (JmxException e1) 1543 { 1544 logger.error(Translate.get( 1545 "virtualdatabase.fail.unregister.backend.mbean", db.getName()), e1); 1546 } 1547 } 1548 1549 if (logger.isDebugEnabled()) 1550 logger.debug("Backend " + db.getName() + " removed successfully"); 1551 } 1552 1553 1557 public void transferBackend(String backend, String controllerDestination) 1558 throws VirtualDatabaseException 1559 { 1560 throw new VirtualDatabaseException("Cannot transfer backend to controller:" 1561 + controllerDestination + " because database is not distributed"); 1562 } 1563 1564 1568 1571 public String [] getBackuperNames() 1572 { 1573 return requestManager.getBackupManager().getBackuperNames(); 1574 } 1575 1576 1579 public String getDumpFormatForBackuper(String backuperName) 1580 { 1581 Backuper backuper = requestManager.getBackupManager().getBackuperByName( 1582 backuperName); 1583 if (backuper == null) 1584 { 1585 return null; 1586 } 1587 return backuper.getDumpFormat(); 1588 } 1589 1590 1594 public void backupBackend(String backendName, String login, String password, 1595 String dumpName, String backuperName, String path, ArrayList tables) 1596 throws VirtualDatabaseException 1597 { 1598 try 1599 { 1600 DatabaseBackend db = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 1601 requestManager.backupBackend(db, login, password, dumpName, backuperName, 1602 path, tables); 1603 } 1604 catch (SQLException sql) 1605 { 1606 throw new VirtualDatabaseException(sql); 1607 } 1608 } 1609 1610 1613 public DumpInfo[] getAvailableDumps() throws VirtualDatabaseException 1614 { 1615 try 1616 { 1617 RecoveryLog recoveryLog = requestManager.getRecoveryLog(); 1618 if (recoveryLog == null) 1619 { 1620 return new DumpInfo[0]; 1621 } 1622 else 1623 { 1624 ArrayList dumps = recoveryLog.getDumpList(); 1625 return (DumpInfo[]) dumps.toArray(new DumpInfo[dumps.size()]); 1626 } 1627 } 1628 catch (SQLException e) 1629 { 1630 throw new VirtualDatabaseException(e); 1631 } 1632 } 1633 1634 1638 public void updateDumpPath(String dumpName, String newPath) 1639 throws VirtualDatabaseException 1640 { 1641 try 1642 { 1643 RecoveryLog recoveryLog = requestManager.getRecoveryLog(); 1644 if (recoveryLog == null) 1645 { 1646 throw new VirtualDatabaseException("no recovery log"); } 1648 else 1649 { 1650 recoveryLog.updateDumpPath(dumpName, newPath); 1651 } 1652 } 1653 catch (SQLException e) 1654 { 1655 throw new VirtualDatabaseException(e); 1656 } 1657 } 1658 1659 1662 public boolean removeDump(String dumpName) 1663 { 1664 if (dumpName == null) 1665 { 1666 return false; 1667 } 1668 RecoveryLog recoveryLog = requestManager.getRecoveryLog(); 1669 if (recoveryLog == null) 1670 { 1671 return false; 1672 } 1673 else 1674 { 1675 try 1676 { 1677 DumpInfo dumpInfo = recoveryLog.getDumpInfo(dumpName); 1678 if (dumpInfo == null) 1679 { 1680 return false; 1681 } 1682 Backuper backuper = requestManager.getBackupManager() 1683 .getBackuperByFormat(dumpInfo.getDumpFormat()); 1684 if (backuper == null) 1685 { 1686 return false; 1687 } 1688 recoveryLog.removeDump(dumpInfo); 1689 backuper.deleteDump(dumpInfo.getDumpPath(), dumpInfo.getDumpName()); 1690 return true; 1691 } 1692 catch (Exception e) 1693 { 1694 String msg = Translate.get("virtualdatabase.removeDump.failure", 1695 new String []{dumpName, e.getMessage()}); 1696 logger.error(msg); 1697 return false; 1698 } 1699 } 1700 } 1701 1702 1708 public void removeCheckpoint(String checkpointName) 1709 throws VirtualDatabaseException 1710 { 1711 try 1712 { 1713 requestManager.removeCheckpoint(checkpointName); 1714 } 1715 catch (Exception e) 1716 { 1717 throw new VirtualDatabaseException(e.getMessage()); 1718 } 1719 } 1720 1721 1725 public void restoreDumpOnBackend(String databaseBackendName, String login, 1726 String password, String dumpName, ArrayList tables) 1727 throws VirtualDatabaseException 1728 { 1729 DatabaseBackend backend = getAndCheckBackend(databaseBackendName, 1730 NO_CHECK_BACKEND); 1731 try 1734 { 1735 requestManager.restoreBackendFromBackupCheckpoint(backend, login, 1736 password, dumpName, tables); 1737 } 1738 catch (BackupException e) 1739 { 1740 throw new VirtualDatabaseException(e); 1741 } 1742 } 1743 1744 1747 public void setBackendLastKnownCheckpoint(String backendName, 1748 String checkpoint) throws VirtualDatabaseException 1749 { 1750 RecoveryLog log = requestManager.getRecoveryLog(); 1751 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 1752 if (log == null) 1753 throw new VirtualDatabaseException("No recovery log has been defined"); 1754 else 1755 { 1756 if (!backend.isDisabled()) 1757 throw new VirtualDatabaseException( 1758 "Cannot setLastKnownCheckpoint on a non-disabled backend"); 1759 else 1760 { 1761 try 1762 { 1763 log.storeBackendRecoveryInfo(this.name, 1764 new BackendRecoveryInfo(backend.getName(), checkpoint, backend 1765 .getStateValue(), this.name)); 1766 1767 backend.setLastKnownCheckpoint(checkpoint); 1768 } 1769 catch (SQLException e) 1770 { 1771 throw new VirtualDatabaseException( 1772 "Failed to store recovery info for backend '" + backendName 1773 + "' (" + e + ")"); 1774 } 1775 } 1776 } 1777 } 1778 1779 1782 public ArrayList viewCheckpointNames() 1783 { 1784 try 1785 { 1786 RecoveryLog recoveryLog = requestManager.getRecoveryLog(); 1787 if (recoveryLog == null) 1788 return new ArrayList (); 1789 else 1790 return recoveryLog.getCheckpointNames(); 1791 } 1792 catch (SQLException e) 1793 { 1794 return new ArrayList (); 1795 } 1796 } 1797 1798 1802 1805 public void addCurrentNbOfThread() 1806 { 1807 currentNbOfThreads++; 1808 } 1809 1810 1814 public void addIdleThread() 1815 { 1816 idleThreads++; 1817 } 1818 1819 1822 public int getCurrentNbOfThreads() 1823 { 1824 return currentNbOfThreads; 1825 } 1826 1827 1833 public int getIdleThreads() 1834 { 1835 return idleThreads; 1836 } 1837 1838 1843 public int getMaxNbOfThreads() 1844 { 1845 return maxNbOfThreads; 1846 } 1847 1848 1853 public long getMaxThreadIdleTime() 1854 { 1855 return maxThreadIdleTime; 1856 } 1857 1858 1863 public int getMinNbOfThreads() 1864 { 1865 return minNbOfThreads; 1866 } 1867 1868 1873 public boolean isPoolConnectionThreads() 1874 { 1875 return poolConnectionThreads; 1876 } 1877 1878 1882 public void removeCurrentNbOfThread() 1883 { 1884 currentNbOfThreads--; 1885 } 1886 1887 1891 public void removeIdleThread() 1892 { 1893 idleThreads--; 1894 } 1895 1896 1901 public void setMaxThreadIdleTime(long maxThreadIdleTime) 1902 { 1903 this.maxThreadIdleTime = maxThreadIdleTime; 1904 } 1905 1906 1911 public void setMinNbOfThreads(int minNbOfThreads) 1912 { 1913 this.minNbOfThreads = minNbOfThreads; 1914 } 1915 1916 1921 public void setPoolConnectionThreads(boolean poolConnectionThreads) 1922 { 1923 this.poolConnectionThreads = poolConnectionThreads; 1924 } 1925 1926 1930 1935 public ArrayList getActiveThreads() 1936 { 1937 return activeThreads; 1938 } 1939 1940 1945 public AuthenticationManager getAuthenticationManager() 1946 { 1947 return authenticationManager; 1948 } 1949 1950 1953 public String getBackendInformation(String backendName) 1954 throws VirtualDatabaseException 1955 { 1956 try 1957 { 1958 acquireReadLockBackendLists(); 1959 } 1960 catch (InterruptedException e) 1961 { 1962 String msg = "Unable to acquire read lock on backend list in getBackendInformation (" 1963 + e + ")"; 1964 logger.error(msg); 1965 throw new VirtualDatabaseException(msg); 1966 } 1967 1968 int size = backends.size(); 1970 DatabaseBackend b = null; 1971 for (int i = 0; i < size; i++) 1972 { 1973 b = (DatabaseBackend) backends.get(i); 1974 if (b.getName().equals(backendName)) 1975 break; 1976 else 1977 b = null; 1978 } 1979 1980 if (b == null) 1981 { 1982 releaseReadLockBackendLists(); 1983 String msg = "Backend " + backendName + " does not exists."; 1984 logger.warn(msg); 1985 throw new VirtualDatabaseException(msg); 1986 } 1987 1988 releaseReadLockBackendLists(); 1989 return b.getXml(); 1990 } 1991 1992 1997 public ArrayList getBackends() 1998 { 1999 return backends; 2000 } 2001 2002 2005 public String getBackendSchema(String backendName) 2006 throws VirtualDatabaseException 2007 { 2008 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 2009 try 2012 { 2013 return XmlTools.prettyXml(backend.getSchemaXml(true)); 2014 } 2015 catch (Exception e) 2016 { 2017 throw new VirtualDatabaseException(e.getMessage()); 2018 } 2019 } 2020 2021 2024 public String getBackendState(String backendName) 2025 throws VirtualDatabaseException 2026 { 2027 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 2028 return backend.getState(); 2029 } 2030 2031 2036 public AbstractBlobFilter getBlobFilter() 2037 { 2038 return blobFilter; 2039 } 2040 2041 2049 public String getDatabaseName() 2050 { 2051 return name; 2052 } 2053 2054 2057 public String getDatabaseProductName() 2058 { 2059 return databaseProductNames; 2060 } 2061 2062 2066 public VirtualDatabaseDynamicMetaData getDynamicMetaData() 2067 { 2068 if (metadata == null) 2069 { 2070 metadata = new VirtualDatabaseDynamicMetaData(this); 2071 } 2072 return metadata; 2073 } 2074 2075 2082 public DatabaseSchema getDatabaseSchemaFromActiveBackends() 2083 throws SQLException 2084 { 2085 boolean isRaidb1 = requestManager.getLoadBalancer().getRAIDbLevel() == RAIDbLevels.RAIDb1; 2086 2087 try 2088 { 2089 acquireReadLockBackendLists(); 2090 } 2091 catch (InterruptedException e) 2092 { 2093 String msg = "Unable to acquire read lock on backend list in getDatabaseSchemaFromActiveBackends (" 2094 + e + ")"; 2095 logger.error(msg); 2096 throw new SQLException (msg); 2097 } 2098 2099 int size = backends.size(); 2101 DatabaseSchema schema = null; 2102 DatabaseBackend b = null; 2103 for (int i = 0; i < size; i++) 2104 { 2105 b = (DatabaseBackend) backends.get(i); 2106 if (b.isReadEnabled()) 2107 { 2108 if (schema == null) 2109 schema = new DatabaseSchema(b.getDatabaseSchema()); 2110 else 2111 schema.mergeSchema(b.getDatabaseSchema()); 2112 2113 if (isRaidb1) 2116 break; 2117 } 2118 } 2119 2120 2123 releaseReadLockBackendLists(); 2124 2125 return schema; 2126 } 2127 2128 2135 public DatabaseSchema getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames() 2136 throws SQLException 2137 { 2138 try 2139 { 2140 acquireReadLockBackendLists(); 2141 } 2142 catch (InterruptedException e) 2143 { 2144 String msg = "Unable to acquire read lock on backend list in getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames (" 2145 + e + ")"; 2146 logger.error(msg); 2147 throw new SQLException (msg); 2148 } 2149 2150 int size = backends.size(); 2152 DatabaseSchema schema = null; 2153 DatabaseBackend b = null; 2154 String dbProductNames = "C-JDBC"; 2155 for (int i = 0; i < size; i++) 2156 { 2157 b = (DatabaseBackend) backends.get(i); 2158 if (b.isReadEnabled()) 2159 { 2160 if (schema == null) 2161 schema = new DatabaseSchema(b.getDatabaseSchema()); 2162 else 2163 schema.mergeSchema(b.getDatabaseSchema()); 2164 } 2165 2166 if (dbProductNames.indexOf(b.getDatabaseProductName()) == -1) 2168 dbProductNames += "," + b.getDatabaseProductName(); 2169 } 2170 2171 releaseReadLockBackendLists(); 2172 databaseProductNames = dbProductNames; 2173 2174 2177 return schema; 2178 } 2179 2180 2185 public int getMaxNbOfConnections() 2186 { 2187 return maxNbOfConnections; 2188 } 2189 2190 2195 public ArrayList getPendingConnections() 2196 { 2197 return pendingConnections; 2198 } 2199 2200 2205 public RequestManager getRequestManager() 2206 { 2207 return requestManager; 2208 } 2209 2210 2217 public VirtualDatabaseStaticMetaData getStaticMetaData() 2218 { 2219 if (staticMetadata == null) 2220 { 2221 staticMetadata = new VirtualDatabaseStaticMetaData(this); 2222 } 2223 return staticMetadata; 2224 } 2225 2226 2231 public String getVirtualDatabaseName() 2232 { 2233 return name; 2234 } 2235 2236 2242 public SQLMonitoring getSQLMonitor() 2243 { 2244 return sqlMonitor; 2245 } 2246 2247 2253 public int getSQLShortFormLength() 2254 { 2255 return sqlShortFormLength; 2256 } 2257 2258 2263 public LinkedList getTotalOrderQueue() 2264 { 2265 return totalOrderQueue; 2266 } 2267 2268 2271 public boolean hasRecoveryLog() 2272 { 2273 RecoveryLog log = requestManager.getRecoveryLog(); 2274 if (log == null) 2275 return false; 2276 else 2277 return true; 2278 } 2279 2280 2283 public boolean hasResultCache() 2284 { 2285 AbstractResultCache cache = requestManager.getResultCache(); 2286 if (cache == null) 2287 return false; 2288 else 2289 return true; 2290 } 2291 2292 2298 public void setAuthenticationManager( 2299 AuthenticationManager authenticationManager) 2300 { 2301 this.authenticationManager = authenticationManager; 2302 } 2303 2304 2309 public void setBlobFilter(AbstractBlobFilter filter) 2310 { 2311 this.blobFilter = filter; 2312 } 2313 2314 2321 public void setStaticDatabaseSchema(DatabaseSchema schema) 2322 { 2323 if (requestManager != null) 2324 requestManager.setDatabaseSchema(schema, true); 2325 else 2326 logger 2327 .warn("Unable to set database schema, no request manager has been defined."); 2328 } 2329 2330 2335 public void setMaxNbOfConnections(int maxNbOfConnections) 2336 { 2337 this.maxNbOfConnections = maxNbOfConnections; 2338 } 2339 2340 2345 public void setMaxNbOfThreads(int maxNbOfThreads) 2346 { 2347 this.maxNbOfThreads = maxNbOfThreads; 2348 } 2349 2350 2355 public void setRequestManager(RequestManager requestManager) 2356 { 2357 this.requestManager = requestManager; 2358 } 2359 2360 2365 public void setSQLMonitor(SQLMonitoring sqlMonitor) 2366 { 2367 this.sqlMonitor = sqlMonitor; 2368 } 2369 2370 2375 public void setTotalOrderQueue(LinkedList newQueue) 2376 { 2377 if (totalOrderQueue != null) 2378 { 2379 if (totalOrderQueue.isEmpty()) 2380 logger.info("Overriding local total order queue"); 2381 else 2382 logger.error("Non-empty local order queue redefined (still contains" 2383 + totalOrderQueue.size() + " entries)"); 2384 } 2385 totalOrderQueue = newQueue; 2386 } 2387 2388 2391 public void setMonitoringToActive(boolean active) 2392 throws VirtualDatabaseException 2393 { 2394 if (sqlMonitor == null) 2395 throw new VirtualDatabaseException(Translate 2396 .get("virtualdatabase.monitoring.not.defined")); 2397 else 2398 sqlMonitor.setActive(active); 2399 } 2400 2401 2407 public boolean equals(Object other) 2408 { 2409 if ((other == null) || (!(other instanceof VirtualDatabase))) 2410 return false; 2411 else 2412 { 2413 VirtualDatabase db = (VirtualDatabase) other; 2414 return name.equals(db.getDatabaseName()); 2415 } 2416 } 2417 2418 2422 2425 public void cleanMonitoringData() throws VirtualDatabaseException 2426 { 2427 if (sqlMonitor == null) 2428 throw new VirtualDatabaseException(Translate 2429 .get("virtualdatabase.monitoring.not.defined")); 2430 else 2431 sqlMonitor.cleanStats(); 2432 } 2433 2434 2437 public String [][] retrieveBackendsData() throws VirtualDatabaseException 2438 { 2439 try 2440 { 2441 acquireReadLockBackendLists(); 2442 } 2443 catch (InterruptedException e) 2444 { 2445 String msg = Translate.get("virtualdatabase.fail.read.lock", e); 2446 throw new VirtualDatabaseException(msg); 2447 } 2448 ArrayList localBackends = this.getBackends(); 2449 int backendListSize = localBackends.size(); 2450 String [][] data = new String [backendListSize][]; 2451 for (int i = 0; i < backendListSize; i++) 2452 { 2453 data[i] = ((DatabaseBackend) localBackends.get(i)).getBackendData(); 2454 } 2455 releaseReadLockBackendLists(); 2456 return data; 2457 } 2458 2459 2462 public BackendStatistics getBackendStatistics(String backendName) 2463 throws VirtualDatabaseException 2464 { 2465 try 2466 { 2467 acquireReadLockBackendLists(); 2468 } 2469 catch (InterruptedException e) 2470 { 2471 String msg = Translate.get("virtualdatabase.fail.read.lock", e); 2472 throw new VirtualDatabaseException(msg); 2473 } 2474 BackendStatistics stat = null; 2475 ArrayList backendList = this.getBackends(); 2476 for (Iterator iter = backendList.iterator(); iter.hasNext();) 2477 { 2478 DatabaseBackend backend = (DatabaseBackend) iter.next(); 2479 if (backend.getName().equals(backendName)) 2480 { 2481 stat = backend.getBackendStats(); 2482 } 2483 } 2484 releaseReadLockBackendLists(); 2485 return stat; 2486 } 2487 2488 2493 public boolean isShuttingDown() 2494 { 2495 return shuttingDown; 2496 } 2497 2498 2501 public void shutdown(int level) 2502 { 2503 VirtualDatabaseShutdownThread vdst = null; 2504 synchronized (this) 2505 { 2506 if (shuttingDown) 2507 return; 2508 switch (level) 2509 { 2510 case Constants.SHUTDOWN_WAIT : 2511 vdst = new VirtualDatabaseWaitShutdownThread(this); 2512 logger.info(Translate.get("controller.shutdown.type.wait", this 2513 .getVirtualDatabaseName())); 2514 break; 2515 case Constants.SHUTDOWN_SAFE : 2516 shuttingDown = true; 2517 vdst = new VirtualDatabaseSafeShutdownThread(this); 2518 logger.info(Translate.get("controller.shutdown.type.safe", this 2519 .getVirtualDatabaseName())); 2520 break; 2521 case Constants.SHUTDOWN_FORCE : 2522 shuttingDown = true; 2523 vdst = new VirtualDatabaseForceShutdownThread(this); 2524 logger.warn(Translate.get("controller.shutdown.type.force", this 2525 .getVirtualDatabaseName())); 2526 break; 2527 default : 2528 String msg = Translate 2529 .get("controller.shutdown.unknown.level", level); 2530 logger.error(msg); 2531 throw new RuntimeException (msg); 2532 } 2533 } 2534 2535 new Thread (vdst.getShutdownGroup(), vdst, "VirtualDatabase Shutdown Thread") 2536 .start(); 2537 } 2538 2539 2542 public void storeBackendsInfo() 2543 { 2544 requestManager.storeBackendsInfo(this.name, getBackends()); 2545 } 2546 2547 2553 public ArrayList viewAllClientNames() 2554 { 2555 ArrayList list = this.getActiveThreads(); 2556 int size = list.size(); 2557 ArrayList clients = new ArrayList (size); 2558 for (int i = 0; i < list.size(); i++) 2559 clients.add(((VirtualDatabaseWorkerThread) list.get(i)).getUser()); 2560 return clients; 2561 } 2562 2563 2566 public String [] viewBackendInformation(String backendName) 2567 throws VirtualDatabaseException 2568 { 2569 DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND); 2570 return backend.getBackendData(); 2571 } 2572 2573 2576 public String [] viewControllerList() 2577 { 2578 return new String []{viewOwningController()}; 2579 } 2580 2581 2584 public Hashtable viewGroupBackends() throws VirtualDatabaseException 2585 { 2586 Hashtable map = new Hashtable (); 2587 try 2588 { 2589 acquireReadLockBackendLists(); 2590 } 2591 catch (InterruptedException e) 2592 { 2593 String msg = "Unable to acquire read lock on backend list in getAllBackendNames (" 2594 + e + ")"; 2595 logger.error(msg); 2596 throw new VirtualDatabaseException(msg); 2597 } 2598 2599 int size = backends.size(); 2601 ArrayList backendInfos = new ArrayList (size); 2602 for (int i = 0; i < size; i++) 2603 backendInfos.add(new BackendInfo(((DatabaseBackend) backends.get(i)))); 2604 2605 releaseReadLockBackendLists(); 2606 2607 map.put(controller.getJmxName(), backendInfos); 2609 return map; 2610 } 2611 2612 2615 public String viewOwningController() 2616 { 2617 return controller.getJmxName(); 2618 } 2619 2620 2623 public String getAssociatedString() 2624 { 2625 return "virtualdatabase"; 2626 } 2627 2628 2633 public String getXml() 2634 { 2635 StringBuffer info = new StringBuffer (); 2636 info.append("<" + DatabasesXmlTags.ELT_VirtualDatabase + " " 2637 + DatabasesXmlTags.ATT_name + "=\"" + this.getVirtualDatabaseName() 2638 + "\" " + DatabasesXmlTags.ATT_maxNbOfConnections + "=\"" 2639 + this.getMaxNbOfConnections() + "\" " 2640 + DatabasesXmlTags.ATT_poolThreads + "=\"" 2641 + this.isPoolConnectionThreads() + "\" " 2642 + DatabasesXmlTags.ATT_minNbOfThreads + "=\"" 2643 + this.getMinNbOfThreads() + "\" " 2644 + DatabasesXmlTags.ATT_maxNbOfThreads + "=\"" 2645 + this.getMaxNbOfThreads() + "\" " 2646 + DatabasesXmlTags.ATT_maxThreadIdleTime + "=\"" 2647 + this.getMaxThreadIdleTime() / 1000 + "\" " 2648 + DatabasesXmlTags.ATT_sqlDumpLength + "=\"" + this.sqlShortFormLength 2649 + "\" " + DatabasesXmlTags.ATT_blobEncodingMethod + "=\"" 2650 + this.blobFilter.getXml() + "\">"); 2651 2652 info.append(getDistributionXml()); 2653 2654 if (this.getSQLMonitor() != null) 2655 info.append(sqlMonitor.getXml()); 2656 2657 info.append(requestManager.getBackupManager().getXml()); 2658 2659 if (this.getAuthenticationManager() != null) 2660 info.append(authenticationManager.getXml()); 2661 2662 try 2663 { 2664 acquireReadLockBackendLists(); 2665 int size = backends.size(); 2666 for (int i = 0; i < size; i++) 2667 info.append(((DatabaseBackend) backends.get(i)).getXml()); 2668 releaseReadLockBackendLists(); 2669 } 2670 catch (InterruptedException e) 2671 { 2672 logger.error(Translate.get("virtualdatabase.fail.read.lock", e)); 2673 } 2674 if (requestManager != null) 2675 info.append(requestManager.getXml()); 2676 info.append("</" + DatabasesXmlTags.ELT_VirtualDatabase + ">"); 2677 return info.toString(); 2678 } 2679 2680 2685 protected String getDistributionXml() 2686 { 2687 return ""; 2688 } 2689 2690 2693 public void deleteLogUpToCheckpoint(String checkpointName) 2694 throws VirtualDatabaseException 2695 { 2696 if (!hasRecoveryLog()) 2697 throw new VirtualDatabaseException(Translate 2698 .get("virtualdatabase.no.recovery.log")); 2699 2700 try 2701 { 2702 getRequestManager().getRecoveryLog().deleteLogEntriesBeforeCheckpoint( 2703 checkpointName); 2704 } 2705 catch (SQLException e) 2706 { 2707 throw new VirtualDatabaseException(e); 2708 } 2709 } 2710 2711 2715 public void copyLogFromCheckpoint(String dumpName, String controllerName) 2716 throws VirtualDatabaseException 2717 { 2718 if (!hasRecoveryLog()) 2719 throw new VirtualDatabaseException(Translate 2720 .get("virtualdatabase.no.recovery.log")); 2721 if (!isDistributed()) 2722 throw new VirtualDatabaseException(Translate 2723 .get("virtualdatabase.not.distributed")); 2724 2725 2731 } 2732 2733 2746 public void setCheckpoint(String checkpointName) 2747 throws VirtualDatabaseException 2748 { 2749 if (!hasRecoveryLog()) 2750 throw new VirtualDatabaseException(Translate 2751 .get("virtualdatabase.no.recovery.log")); 2752 2753 try 2754 { 2755 logger.info(Translate.get("requestmanager.wait.pending.writes")); 2757 getRequestManager().getScheduler().suspendWrites(); 2758 2759 getRequestManager().getRecoveryLog().storeCheckpoint(checkpointName); 2761 logger.info(Translate.get("recovery.checkpoint.stored", checkpointName)); 2762 2763 logger.info(Translate.get("requestmanager.resume.pending.writes")); 2765 getRequestManager().getScheduler().resumeWrites(); 2766 2767 } 2768 catch (SQLException e) 2769 { 2770 String msg = "set checkpoint failed"; 2771 logger.error(msg, e); 2772 throw new VirtualDatabaseException(msg, e); 2773 } 2774 } 2775 2776 2780 public void copyDump(String dumpName, String remoteControllerName) 2781 throws VirtualDatabaseException 2782 { 2783 if (!isDistributed()) 2784 throw new VirtualDatabaseException( 2785 "can not copy dumps on non-distributed virtual database"); 2786 } 2787 2788 2792 public void transferDump(String dumpName, String remoteControllerName, 2793 boolean noCopy) throws VirtualDatabaseException 2794 { 2795 if (!isDistributed()) 2796 throw new VirtualDatabaseException( 2797 "can not transfer dumps on non-distributed virtual database"); 2798 } 2799 2800} | Popular Tags |