src/org/objectweb/cjdbc/controller/backend/DatabaseBackend.java

説明を見る。
00001 00025 package org.objectweb.cjdbc.controller.backend; 00026 00027 import java.io.Serializable; 00028 import java.io.StringReader; 00029 import java.net.ConnectException; 00030 import java.sql.Connection; 00031 import java.sql.SQLException; 00032 import java.sql.Statement; 00033 import java.util.ArrayList; 00034 import java.util.HashMap; 00035 import java.util.Hashtable; 00036 import java.util.Iterator; 00037 import java.util.Map; 00038 import java.util.Vector; 00039 00040 import javax.management.NotCompliantMBeanException; 00041 00042 import org.dom4j.Document; 00043 import org.dom4j.Element; 00044 import org.dom4j.io.SAXReader; 00045 import org.objectweb.cjdbc.common.i18n.Translate; 00046 import org.objectweb.cjdbc.common.jmx.mbeans.DatabaseBackendMBean; 00047 import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList; 00048 import org.objectweb.cjdbc.common.log.Trace; 00049 import org.objectweb.cjdbc.common.shared.BackendInfo; 00050 import org.objectweb.cjdbc.common.shared.BackendState; 00051 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema; 00052 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags; 00053 import org.objectweb.cjdbc.common.xml.XmlComponent; 00054 import org.objectweb.cjdbc.controller.backend.rewriting.AbstractRewritingRule; 00055 import org.objectweb.cjdbc.controller.connection.AbstractConnectionManager; 00056 import org.objectweb.cjdbc.controller.connection.FailFastPoolConnectionManager; 00057 import org.objectweb.cjdbc.controller.connection.RandomWaitPoolConnectionManager; 00058 import org.objectweb.cjdbc.controller.connection.SimpleConnectionManager; 00059 import org.objectweb.cjdbc.controller.connection.VariablePoolConnectionManager; 00060 import org.objectweb.cjdbc.controller.jmx.AbstractStandardMBean; 00061 import org.objectweb.cjdbc.controller.jmx.MBeanServerManager; 00062 import org.objectweb.cjdbc.controller.jmx.RmiConnector; 00063 00075 public class DatabaseBackend extends AbstractStandardMBean 00076 implements 00077 Serializable, 00078 XmlComponent, 00079 DatabaseBackendMBean 00080 { 00081 // 00082 // How the code is organized? 00083 // 1. Member variables 00084 // 2. Constructor(s) 00085 // 3. Lookup functions 00086 // 4. Connections management 00087 // 5. State management 00088 // 6. Getter/Setter (possibly in alphabetical order) 00089 // 7. Debug/Monitoring 00090 // 00091 00093 private String name; 00094 00096 private String driverPath; 00097 00099 private String driverClassName; 00100 00102 private transient DriverCompliance driverCompliance; 00103 00105 private String url; 00106 00108 private boolean writeCanBeEnabled; 00109 00111 private String connectionTestStatement; 00112 00114 private DatabaseSchema schema; 00115 00117 private boolean schemaIsStatic = false; 00118 00120 private transient HashMap connectionManagers; 00121 00123 protected transient Trace logger; 00124 00126 private transient ArrayList activeTransactions = new ArrayList(); 00127 00129 private transient Vector pendingRequests = new Vector(); 00130 00132 private int totalRequest; 00133 private int totalWriteRequest; 00134 private int totalReadRequest; 00135 private int totalTransactions; 00136 00138 private ArrayList rewritingRules; 00139 00141 private int dynamicPrecision; 00142 private boolean gatherSystemTables = false; 00143 00145 private int sqlShortFormLength = 40; 00146 00147 private String lastKnownCheckpoint; 00148 00154 private int state = BackendState.DISABLED; 00155 00156 private transient BackendStateListener stateListener; 00157 00172 public DatabaseBackend(String name, String driverPath, 00173 String driverClassName, String url, boolean writeCanBeEnabled, 00174 String connectionTestStatement) throws NotCompliantMBeanException 00175 { 00176 super(DatabaseBackendMBean.class); 00177 if (name == null) 00178 throw new IllegalArgumentException(Translate 00179 .get("backend.null.backend.name")); 00180 00181 if (driverClassName == null) 00182 throw new IllegalArgumentException(Translate.get("backend.null.driver")); 00183 00184 if (url == null) 00185 throw new IllegalArgumentException(Translate.get("backend.null.url")); 00186 00187 if (connectionTestStatement == null) 00188 throw new IllegalArgumentException(Translate 00189 .get("backend.null.connection.test")); 00190 00191 this.name = name; 00192 this.writeCanBeEnabled = writeCanBeEnabled; 00193 this.driverPath = driverPath; 00194 this.driverClassName = driverClassName; 00195 this.url = url; 00196 this.connectionTestStatement = connectionTestStatement; 00197 this.connectionManagers = new HashMap(); 00198 logger = Trace 00199 .getLogger("org.objectweb.cjdbc.controller.backend.DatabaseBackend." 00200 + name); 00201 this.driverCompliance = new DriverCompliance(logger); 00202 totalRequest = 0; 00203 dynamicPrecision = DatabaseBackendSchemaConstants.DynamicPrecisionAll; 00204 } 00205 00213 public DatabaseBackend(BackendInfo info) throws NotCompliantMBeanException 00214 { 00215 this(info.getName(), info.getDriverPath(), info.getDriverClassName(), info 00216 .getUrl(), true, info.getConnectionTestStatement()); 00217 try 00218 { 00219 String xml = info.getXml(); 00220 StringReader sreader = new StringReader(xml); 00221 SAXReader reader = new SAXReader(); 00222 Document document = reader.read(sreader); 00223 Element root = document.getRootElement(); 00224 Iterator iter1 = root.elementIterator(); 00225 while (iter1.hasNext()) 00226 { 00227 Element elem = (Element) iter1.next(); 00228 if (elem.getName().equals(DatabasesXmlTags.ELT_ConnectionManager)) 00229 { 00230 String vuser = elem.valueOf("@" + DatabasesXmlTags.ATT_vLogin); 00231 String rlogin = elem.valueOf("@" + DatabasesXmlTags.ATT_rLogin); 00232 String rpassword = elem.valueOf("@" + DatabasesXmlTags.ATT_rPassword); 00233 Iterator iter2 = elem.elementIterator(); 00234 while (iter2.hasNext()) 00235 { 00236 Element connectionManager = (Element) iter2.next(); 00237 String cname = connectionManager.getName(); 00238 if (cname 00239 .equals(DatabasesXmlTags.ELT_VariablePoolConnectionManager)) 00240 { 00241 int minPoolSize = Integer.parseInt(connectionManager.valueOf("@" 00242 + DatabasesXmlTags.ATT_minPoolSize)); 00243 int maxPoolSize = Integer.parseInt(connectionManager.valueOf("@" 00244 + DatabasesXmlTags.ATT_maxPoolSize)); 00245 int idleTimeout = Integer.parseInt(connectionManager.valueOf("@" 00246 + DatabasesXmlTags.ATT_idleTimeout)); 00247 int waitTimeout = Integer.parseInt(connectionManager.valueOf("@" 00248 + DatabasesXmlTags.ATT_waitTimeout)); 00249 this.addConnectionManager(vuser, 00250 new VariablePoolConnectionManager(url, name, rlogin, 00251 rpassword, driverPath, driverClassName, minPoolSize, 00252 maxPoolSize, idleTimeout, waitTimeout)); 00253 } 00254 else if (cname.equals(DatabasesXmlTags.ELT_SimpleConnectionManager)) 00255 { 00256 this.addConnectionManager(vuser, new SimpleConnectionManager(url, 00257 name, rlogin, rpassword, driverPath, driverClassName)); 00258 } 00259 else if (cname 00260 .equals(DatabasesXmlTags.ELT_RandomWaitPoolConnectionManager)) 00261 { 00262 int poolSize = Integer.parseInt(connectionManager.valueOf("@" 00263 + DatabasesXmlTags.ATT_poolSize)); 00264 int timeout = Integer.parseInt(connectionManager.valueOf("@" 00265 + DatabasesXmlTags.ATT_timeout)); 00266 this 00267 .addConnectionManager(vuser, 00268 new RandomWaitPoolConnectionManager(url, name, rlogin, 00269 rpassword, driverPath, driverClassName, poolSize, 00270 timeout)); 00271 } 00272 else if (cname 00273 .equals(DatabasesXmlTags.ELT_FailFastPoolConnectionManager)) 00274 { 00275 int poolSize = Integer.parseInt(connectionManager.valueOf("@" 00276 + DatabasesXmlTags.ATT_poolSize)); 00277 this.addConnectionManager(vuser, 00278 new FailFastPoolConnectionManager(url, name, rlogin, 00279 rpassword, driverPath, driverClassName, poolSize)); 00280 } 00281 } 00282 } 00283 } 00284 00285 } 00286 catch (Exception e) 00287 { 00288 logger 00289 .error(Translate.get("backend.add.connection.manager.failed", e), e); 00290 } 00291 } 00292 00309 public DatabaseBackend(String name, String driverPath, 00310 String driverClassName, String url, String connectionTestStatement, 00311 String dynamicSchemaLevel) throws NotCompliantMBeanException 00312 { 00313 this(name, driverPath, driverClassName, url, true, connectionTestStatement); 00314 this.dynamicPrecision = DatabaseBackendSchemaConstants 00315 .getDynamicSchemaLevel(dynamicSchemaLevel); 00316 } 00317 00323 public void setSqlShortFormLength(int sqlShortFormLength) 00324 { 00325 this.sqlShortFormLength = sqlShortFormLength; 00326 } 00327 00334 public int getSQLShortFormLength() 00335 { 00336 return sqlShortFormLength; 00337 } 00338 00339 /* Lookup functions */ 00340 00348 public boolean equals(Object other) 00349 { 00350 if ((other == null) || (!(other instanceof DatabaseBackend))) 00351 return false; 00352 else 00353 { 00354 DatabaseBackend b = (DatabaseBackend) other; 00355 return name.equals(b.getName()) 00356 && driverClassName.equals(b.getDriverClassName()) 00357 && url.equals(b.getURL()); 00358 } 00359 } 00360 00371 public boolean hasTables(ArrayList tables) 00372 { 00373 if (schema == null) 00374 throw new NullPointerException(Translate.get("backend.schema.not.set")); 00375 00376 if (tables == null) 00377 throw new IllegalArgumentException(Translate.get("backend.null.tables")); 00378 00379 int size = tables.size(); 00380 for (int i = 0; i < size; i++) 00381 { 00382 if (!schema.hasTable((String) tables.get(i))) 00383 return false; 00384 } 00385 return true; 00386 } 00387 00397 public boolean hasTable(String table) 00398 { 00399 if (schema == null) 00400 throw new NullPointerException(Translate.get("backend.schema.not.set")); 00401 00402 return schema.hasTable(table); 00403 } 00404 00410 public ArrayList getTables() 00411 { 00412 if (schema == null) 00413 throw new NullPointerException(Translate.get("backend.schema.not.set")); 00414 return schema.getTables(); 00415 } 00416 00426 public boolean hasStoredProcedure(String procedureName) 00427 { 00428 if (schema == null) 00429 throw new NullPointerException(Translate.get("backend.schema.not.set")); 00430 00431 return schema.hasProcedure(procedureName); 00432 } 00433 00434 /* Connection management */ 00435 00442 public synchronized void initializeConnections() throws SQLException 00443 { 00444 if (connectionManagers.isEmpty()) 00445 throw new SQLException(Translate.get("backend.not.defined", new String[]{ 00446 name, url})); 00447 00448 AbstractConnectionManager connectionManager; 00449 Iterator iter = connectionManagers.values().iterator(); 00450 while (iter.hasNext()) 00451 { 00452 connectionManager = (AbstractConnectionManager) iter.next(); 00453 if (!connectionManager.isInitialized()) 00454 connectionManager.initializeConnections(); 00455 } 00456 } 00457 00464 public synchronized void finalizeConnections() throws SQLException 00465 { 00466 if (connectionManagers.isEmpty()) 00467 throw new SQLException(Translate.get("backend.not.defined", new String[]{ 00468 name, url})); 00469 00470 AbstractConnectionManager connectionManager; 00471 Iterator iter = connectionManagers.values().iterator(); 00472 while (iter.hasNext()) 00473 { 00474 connectionManager = (AbstractConnectionManager) iter.next(); 00475 if (connectionManager.isInitialized()) 00476 connectionManager.finalizeConnections(); 00477 } 00478 } 00479 00489 public final boolean isValidConnection(Connection connection) 00490 { 00491 try 00492 { 00493 Statement s = connection.createStatement(); 00494 s.executeQuery(connectionTestStatement); 00495 } 00496 catch (SQLException e) 00497 { 00498 if ("25P02".equals(e.getSQLState()) 00499 || (e.getMessage() != null && e 00500 .getMessage() 00501 .indexOf( 00502 "current transaction is aborted, queries ignored until end of transaction block") > 0)) 00503 { 00504 // see bug item #300873 on the forge for details 00505 // postgres throws an exception if a query is issued after a request has 00506 // failed within a transaction, we now have to check for this exception 00507 // as it is means the connection is valid 00508 // 00509 // postgres versions after 7.4 will return the SQLState, whereas 00510 // postgres versions prior to 7.4 will have to be checked for the 00511 // message text 00512 return true; 00513 } 00514 return false; 00515 } 00516 return true; 00517 } 00518 00526 public void addConnectionManager(String vLogin, 00527 AbstractConnectionManager connectionManager) 00528 { 00529 if (connectionManager == null) 00530 throw new IllegalArgumentException(Translate.get( 00531 "backend.null.connection.manager", new String[]{name, url})); 00532 if (logger.isInfoEnabled()) 00533 logger.info(Translate.get("backend.add.connection.manager.for.user", 00534 vLogin)); 00535 connectionManager.setVLogin(vLogin); 00536 connectionManagers.put(vLogin, connectionManager); 00537 } 00538 00539 /* State management */ 00540 00547 public void startTransaction(Long tid) 00548 { 00549 synchronized (activeTransactions) 00550 { 00551 totalTransactions++; 00552 activeTransactions.add(tid); 00553 } 00554 } 00555 00562 public void stopTransaction(Long tid) 00563 { 00564 synchronized (activeTransactions) 00565 { 00566 if (!activeTransactions.remove(tid)) 00567 throw new IllegalArgumentException(Translate.get( 00568 "backend.transaction.not.started", new String[]{"" + tid, name})); 00569 // If this was the last open transaction, we notify people possibly 00570 // waiting on waitForAllTransactionsToComplete() 00571 if (activeTransactions.isEmpty()) 00572 { 00573 activeTransactions.notifyAll(); 00574 } 00575 } 00576 } 00577 00583 public void waitForAllTransactionsToComplete() 00584 { 00585 synchronized (activeTransactions) 00586 { 00587 if (activeTransactions.isEmpty()) 00588 return; 00589 else 00590 try 00591 { 00592 activeTransactions.wait(); 00593 } 00594 catch (InterruptedException ignore) 00595 { 00596 } 00597 } 00598 } 00599 00607 public boolean isStartedTransaction(Long tid) 00608 { 00609 return activeTransactions.contains(tid); 00610 } 00611 00618 public final synchronized boolean isInitialized() throws SQLException 00619 { 00620 if (connectionManagers.isEmpty()) 00621 throw new SQLException(Translate.get("backend.null.connection.manager", 00622 new String[]{name, url})); 00623 Iterator iter = connectionManagers.values().iterator(); 00624 while (iter.hasNext()) 00625 { 00626 if (!((AbstractConnectionManager) iter.next()).isInitialized()) 00627 return false; 00628 } 00629 return true; 00630 } 00631 00637 public final synchronized boolean isReadEnabled() 00638 { 00639 return state == BackendState.READ_ENABLED_WRITE_DISABLED 00640 || state == BackendState.READ_ENABLED_WRITE_ENABLED; 00641 } 00642 00648 public final synchronized boolean isWriteEnabled() 00649 { 00650 return state == BackendState.READ_ENABLED_WRITE_ENABLED 00651 || state == BackendState.READ_DISABLED_WRITE_ENABLED 00652 || state == BackendState.DISABLING; 00653 } 00654 00660 public final boolean isRecovering() 00661 { 00662 return state == BackendState.RECOVERING; 00663 } 00664 00670 public final boolean isDisabling() 00671 { 00672 return state == BackendState.DISABLING; 00673 } 00674 00678 public final boolean isDisabled() 00679 { 00680 return state == BackendState.DISABLED; 00681 } 00682 00689 public final boolean isKilled() 00690 { 00691 return state == BackendState.UNKNOWN; 00692 } 00693 00705 public String getState() 00706 { 00707 switch (state) 00708 { 00709 case BackendState.READ_ENABLED_WRITE_DISABLED : 00710 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED; 00711 case BackendState.READ_ENABLED_WRITE_ENABLED : 00712 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED_WRITE; 00713 case BackendState.READ_DISABLED_WRITE_ENABLED : 00714 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED_WRITE; 00715 case BackendState.DISABLING : 00716 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLING; 00717 case BackendState.BACKUPING : 00718 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_BACKINGUP; 00719 case BackendState.RECOVERING : 00720 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_RECOVERING; 00721 case BackendState.DISABLED : 00722 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLED; 00723 case BackendState.UNKNOWN : 00724 return CjdbcNotificationList.VIRTUALDATABASE_BACKEND_UNKNOWN; 00725 default : 00726 throw new IllegalArgumentException("Unknown backend state:" + state); 00727 } 00728 } 00729 00735 public int getStateValue() 00736 { 00737 return state; 00738 } 00739 00744 public synchronized void enableRead() 00745 { 00746 if (isWriteEnabled()) 00747 setState(BackendState.READ_ENABLED_WRITE_ENABLED); 00748 else 00749 setState(BackendState.READ_ENABLED_WRITE_DISABLED); 00750 } 00751 00755 public synchronized void disableRead() 00756 { 00757 if (isWriteEnabled()) 00758 setState(BackendState.READ_DISABLED_WRITE_ENABLED); 00759 else 00760 setState(BackendState.DISABLED); 00761 } 00762 00766 public synchronized void disableWrite() 00767 { 00768 if (isReadEnabled()) 00769 setState(BackendState.READ_ENABLED_WRITE_DISABLED); 00770 else 00771 setState(BackendState.DISABLED); 00772 } 00773 00778 public synchronized void enableWrite() 00779 { 00780 if (isReadEnabled()) 00781 setState(BackendState.READ_ENABLED_WRITE_ENABLED); 00782 else 00783 setState(BackendState.READ_DISABLED_WRITE_ENABLED); 00784 } 00785 00798 public void setDisabling() 00799 { 00800 setState(BackendState.DISABLING); 00801 } 00802 00809 public synchronized void disable() 00810 { 00811 setState(BackendState.DISABLED); 00812 } 00813 00814 /* Getter/setter methods */ 00815 00823 public AbstractConnectionManager getConnectionManager(String vLogin) 00824 { 00825 return (AbstractConnectionManager) connectionManagers.get(vLogin); 00826 } 00827 00834 public HashMap getConnectionManagers() 00835 { 00836 return this.connectionManagers; 00837 } 00838 00844 public String getConnectionTestStatement() 00845 { 00846 return connectionTestStatement; 00847 } 00848 00852 public String getDriverPath() 00853 { 00854 return driverPath; 00855 } 00856 00860 public String getAssociatedString() 00861 { 00862 return "backend"; 00863 } 00864 00870 public String getDriverClassName() 00871 { 00872 return driverClassName; 00873 } 00874 00880 public String getName() 00881 { 00882 return name; 00883 } 00884 00891 public Vector getPendingRequests() 00892 { 00893 return pendingRequests; 00894 } 00895 00902 public void addPendingReadRequest(Object request) 00903 { 00904 synchronized (this) 00905 { 00906 totalRequest++; 00907 totalReadRequest++; 00908 } 00909 pendingRequests.add(request); 00910 } 00911 00918 public void addPendingWriteRequest(Object request) 00919 { 00920 synchronized (this) 00921 { 00922 totalRequest++; 00923 totalWriteRequest++; 00924 } 00925 pendingRequests.add(request); 00926 } 00927 00935 public boolean removePendingRequest(Object request) 00936 { 00937 return pendingRequests.remove(request); 00938 } 00939 00947 public DatabaseSchema getDatabaseSchema() 00948 { 00949 return schema; 00950 } 00951 00959 public void setDatabaseSchema(DatabaseSchema databaseSchema, boolean isStatic) 00960 { 00961 if (schema == null) 00962 { 00963 schemaIsStatic = isStatic; 00964 schema = databaseSchema; 00965 } 00966 else 00967 { 00968 if (!isStatic) 00969 schema = databaseSchema; 00970 } 00971 } 00972 00976 public boolean checkDatabaseSchema() 00977 { 00978 if (logger.isDebugEnabled()) 00979 logger.debug(Translate.get("backend.dynamic.schema", 00980 DatabaseBackendSchemaConstants 00981 .getDynamicSchemaLevel(dynamicPrecision))); 00982 boolean checked = true; 00983 AbstractConnectionManager connectionMananger; 00984 Iterator iter = connectionManagers.values().iterator(); 00985 while (iter.hasNext()) 00986 { 00987 connectionMananger = (AbstractConnectionManager) iter.next(); 00988 00989 // Gather the database schema from this connection manager 00990 DatabaseBackendMetaData meta = new DatabaseBackendMetaData( 00991 connectionMananger, logger, dynamicPrecision, gatherSystemTables); 00992 00993 DatabaseSchema metaSchema; 00994 try 00995 { 00996 if (logger.isInfoEnabled()) 00997 logger.info(Translate.get("backend.gathering.database.schema")); 00998 metaSchema = meta.getDatabaseSchema(); 00999 } 01000 catch (SQLException e) 01001 { 01002 if (logger.isWarnEnabled()) 01003 logger.warn(Translate.get("backend.gather.schema.failed", e)); 01004 return false; 01005 } 01006 if (schema == null) 01007 { 01008 if (logger.isDebugEnabled()) 01009 logger.debug(Translate.get("backend.use.gathered.schema.as.new")); 01010 schema = metaSchema; 01011 } 01012 else 01013 { 01014 if (logger.isInfoEnabled()) 01015 logger.info(Translate.get("backend.check.schema.compatibility")); 01016 if (schema.isCompatibleSubset(metaSchema)) 01017 logger.info(Translate.get("backend.schema.compatible.for.login", 01018 connectionMananger.getLogin())); 01019 else 01020 { 01021 checked = false; 01022 logger.warn(Translate.get("backend.schema.not.compatible.for.login", 01023 connectionMananger.getLogin())); 01024 } 01025 } 01026 } 01027 return checked; 01028 } 01029 01033 public DriverCompliance getDriverCompliance() 01034 { 01035 return driverCompliance; 01036 } 01037 01043 public void checkDriverCompliance() throws SQLException 01044 { 01045 if (connectionManagers.isEmpty()) 01046 throw new SQLException(Translate.get("backend.null.connection.manager", 01047 new String[]{name, url})); 01048 01049 AbstractConnectionManager connectionManager; 01050 Iterator iter = connectionManagers.values().iterator(); 01051 connectionManager = (AbstractConnectionManager) iter.next(); 01052 01053 try 01054 { 01055 if (!driverCompliance.complianceTest(url, connectionManager.getLogin(), 01056 connectionManager.getPassword(), connectionManager.getDriverPath(), 01057 connectionManager.getDriverClassName(), connectionTestStatement)) 01058 throw new SQLException(Translate.get("backend.driver.not.compliant", 01059 driverClassName)); 01060 } 01061 catch (ConnectException e) 01062 { 01063 throw new SQLException(Translate.get("backend.cannot.connect.to", e)); 01064 } 01065 } 01066 01072 public String getURL() 01073 { 01074 return url; 01075 } 01076 01077 /* 01078 * Rewriting Rule management 01079 */ 01080 01086 public void addRewritingRule(AbstractRewritingRule rule) 01087 { 01088 if (rewritingRules == null) 01089 rewritingRules = new ArrayList(); 01090 if (logger.isDebugEnabled()) 01091 logger.debug(Translate.get("backend.rewriting.rule.add", new String[]{ 01092 rule.getQueryPattern(), rule.getRewrite()})); 01093 rewritingRules.add(rule); 01094 } 01095 01102 public final String rewriteQuery(String sqlQuery) 01103 { 01104 if (rewritingRules == null) 01105 return sqlQuery; 01106 int size = rewritingRules.size(); 01107 for (int i = 0; i < size; i++) 01108 { 01109 AbstractRewritingRule rule = (AbstractRewritingRule) rewritingRules 01110 .get(i); 01111 sqlQuery = rule.rewrite(sqlQuery); 01112 if (rule.hasMatched()) 01113 { //Rule matched, query rewriten 01114 if (logger.isDebugEnabled()) 01115 logger.debug(Translate.get("backend.rewriting.query", sqlQuery)); 01116 if (rule.isStopOnMatch()) 01117 break; //Ok, stop here. 01118 } 01119 } 01120 return sqlQuery; 01121 } 01122 01123 /* 01124 * Debug/Monitoring 01125 */ 01126 01132 public String getXml() 01133 { 01134 StringBuffer info = new StringBuffer(); 01135 info.append("<" + DatabasesXmlTags.ELT_DatabaseBackend + " " 01136 + DatabasesXmlTags.ATT_name + "=\"" + name + "\" " 01137 + DatabasesXmlTags.ATT_driver + "=\"" + driverClassName + "\" " 01138 + DatabasesXmlTags.ATT_url + "=\"" + url + "\" " 01139 + DatabasesXmlTags.ATT_connectionTestStatement + "=\"" 01140 + connectionTestStatement + "\">"); 01141 01142 info.append("<" 01143 + DatabasesXmlTags.ELT_DatabaseSchema 01144 + " " 01145 + DatabasesXmlTags.ATT_dynamicPrecision 01146 + "=\"" 01147 + DatabaseBackendSchemaConstants 01148 .getDynamicSchemaLevel(dynamicPrecision) + "\" " 01149 + DatabasesXmlTags.ATT_gatherSystemTables + "=\"" 01150 + (gatherSystemTables ? "true" : "false") + "\">"); 01151 if (this.schema != null && dynamicPrecision ==0) 01152 { 01153 info.append(schema.getXml()); 01154 } 01155 info.append("</" + DatabasesXmlTags.ELT_DatabaseSchema + ">"); 01156 if (rewritingRules != null) 01157 { 01158 int size = rewritingRules.size(); 01159 for (int i = 0; i < size; i++) 01160 info.append(((AbstractRewritingRule) rewritingRules.get(i)).getXml()); 01161 } 01162 if (connectionManagers != null) 01163 { 01164 if (connectionManagers.isEmpty() == false) 01165 { 01166 AbstractConnectionManager connectionManager; 01167 Iterator iter = connectionManagers.values().iterator(); 01168 while (iter.hasNext()) 01169 { 01170 connectionManager = (AbstractConnectionManager) iter.next(); 01171 info.append(connectionManager.getXml()); 01172 } 01173 } 01174 } 01175 info.append("</" + DatabasesXmlTags.ELT_DatabaseBackend + ">"); 01176 return info.toString(); 01177 } 01178 01182 public ArrayList getActiveTransactions() 01183 { 01184 return activeTransactions; 01185 } 01186 01190 public boolean isSchemaStatic() 01191 { 01192 return schemaIsStatic; 01193 } 01194 01200 public String[] getBackendData() 01201 { 01202 String[] data = new String[14]; 01203 data[0] = this.name; 01204 data[1] = this.driverClassName; 01205 data[2] = this.url; 01206 data[3] = String.valueOf(this.activeTransactions.size()); 01207 data[4] = String.valueOf(this.pendingRequests.size()); 01208 data[5] = String.valueOf(this.isReadEnabled()); 01209 data[6] = String.valueOf(this.isWriteEnabled()); 01210 try 01211 { 01212 data[7] = String.valueOf(this.isInitialized()); 01213 } 01214 catch (Exception e) 01215 { 01216 data[7] = "unknown"; 01217 } 01218 data[8] = String.valueOf(this.schemaIsStatic); 01219 01220 data[9] = String.valueOf(this.connectionManagers.size()); 01221 data[10] = String.valueOf(getTotalActiveConnections()); 01222 data[11] = String.valueOf(totalRequest); 01223 data[12] = String.valueOf(totalTransactions); 01224 if (lastKnownCheckpoint == null || lastKnownCheckpoint.equalsIgnoreCase("")) 01225 data[13] = "<unknown>"; 01226 else 01227 data[13] = lastKnownCheckpoint; 01228 return data; 01229 } 01230 01237 public long getTotalActiveConnections() 01238 { 01239 int activeConnections = 0; 01240 Iterator iter = connectionManagers.keySet().iterator(); 01241 while (iter.hasNext()) 01242 activeConnections += ((AbstractConnectionManager) connectionManagers 01243 .get(iter.next())).getCurrentNumberOfConnections(); 01244 return activeConnections; 01245 } 01246 01250 public int getDynamicPrecision() 01251 { 01252 return dynamicPrecision; 01253 } 01254 01259 public void setDynamicPrecision(int dynamicPrecision, 01260 boolean gatherSystemTables) 01261 { 01262 this.dynamicPrecision = dynamicPrecision; 01263 this.gatherSystemTables = gatherSystemTables; 01264 } 01265 01271 public int getTotalTransactions() 01272 { 01273 return totalTransactions; 01274 } 01275 01281 public int getTotalReadRequest() 01282 { 01283 return totalReadRequest; 01284 } 01285 01291 public int getTotalWriteRequest() 01292 { 01293 return totalWriteRequest; 01294 } 01295 01301 public int getTotalRequest() 01302 { 01303 return totalRequest; 01304 } 01305 01311 public void setLastKnownCheckpoint(String checkpoint) 01312 { 01313 this.lastKnownCheckpoint = checkpoint; 01314 } 01315 01321 public String getLastKnownCheckpoint() 01322 { 01323 return lastKnownCheckpoint; 01324 } 01325 01331 public String getDatabaseProductName() 01332 { 01333 return driverCompliance.getDatabaseProductName(); 01334 } 01335 01341 public ArrayList getRewritingRules() 01342 { 01343 return rewritingRules; 01344 } 01345 01351 public void setRewritingRules(ArrayList rewritingRules) 01352 { 01353 this.rewritingRules = rewritingRules; 01354 } 01355 01375 public DatabaseBackend copy(String newName, Map parameters) throws Exception 01376 { 01377 // Get the parameters from the backend if they are not specified, or take 01378 // them from the map of parameters otherwise. 01379 String driverPath = parameters.containsKey(DatabasesXmlTags.ATT_driverPath) 01380 ? (String) parameters.get(DatabasesXmlTags.ATT_driverPath) 01381 : this.getDriverPath(); 01382 01383 String driverClassName = parameters 01384 .containsKey(DatabasesXmlTags.ATT_driver) ? (String) parameters 01385 .get(DatabasesXmlTags.ATT_driver) : this.getDriverClassName(); 01386 01387 String url = parameters.containsKey(DatabasesXmlTags.ATT_url) 01388 ? (String) parameters.get(DatabasesXmlTags.ATT_url) 01389 : this.getURL(); 01390 01391 String connectionTestStatement = parameters 01392 .containsKey(DatabasesXmlTags.ATT_connectionTestStatement) 01393 ? (String) parameters.get(DatabasesXmlTags.ATT_connectionTestStatement) 01394 : this.getConnectionTestStatement(); 01395 01396 // Create the new backend object 01397 DatabaseBackend newBackend = new DatabaseBackend(newName, driverPath, 01398 driverClassName, url, writeCanBeEnabled, connectionTestStatement); 01399 01400 // Set the rewriting rules and the connection managers as the backend we 01401 // are copying 01402 newBackend.setRewritingRules(this.getRewritingRules()); 01403 01404 // Set Connection managers 01405 HashMap connectionManagers = this.getConnectionManagers(); 01406 Iterator iter = connectionManagers.keySet().iterator(); 01407 01408 String vlogin = null; 01409 AbstractConnectionManager connectionManager; 01410 while (iter.hasNext()) 01411 { 01412 vlogin = (String) iter.next(); 01413 connectionManager = (AbstractConnectionManager) connectionManagers 01414 .get(vlogin); 01415 newBackend.addConnectionManager(vlogin, connectionManager.copy(url, 01416 newName)); 01417 } 01418 01419 return newBackend; 01420 01421 } 01422 01428 public boolean isBackuping() 01429 { 01430 return state == BackendState.BACKUPING; 01431 } 01432 01439 public synchronized void setState(int state) 01440 { 01441 switch (state) 01442 { 01443 case BackendState.READ_ENABLED_WRITE_DISABLED : 01444 case BackendState.READ_ENABLED_WRITE_ENABLED : 01445 case BackendState.READ_DISABLED_WRITE_ENABLED : 01446 case BackendState.DISABLING : 01447 case BackendState.BACKUPING : 01448 case BackendState.RECOVERING : 01449 case BackendState.DISABLED : 01450 case BackendState.UNKNOWN : 01451 this.state = state; 01452 if (logger.isDebugEnabled()) 01453 logger.debug(Translate.get("backend.state.changed", new String[]{ 01454 name, getState()})); 01455 notifyStateChange(); 01456 break; 01457 default : 01458 throw new IllegalArgumentException("Unknown backend state:" + state); 01459 } 01460 } 01461 01470 public void notifyStateChange() 01471 { 01472 if (stateListener != null) 01473 stateListener.changeState(this); 01474 01475 notifyJmx(getState()); 01476 } 01477 01484 public void notifyJmx(String type) 01485 { 01486 if (MBeanServerManager.isJmxEnabled()) 01487 { 01488 // Send notification 01489 Hashtable data = new Hashtable(); 01490 data.put(CjdbcNotificationList.DATA_DATABASE, this.name); 01491 data.put(CjdbcNotificationList.DATA_DRIVER, getDriverClassName()); 01492 String checkpoint = getLastKnownCheckpoint(); 01493 checkpoint = (checkpoint == null) ? "" : checkpoint; 01494 data.put(CjdbcNotificationList.DATA_CHECKPOINT, checkpoint); 01495 data.put(CjdbcNotificationList.DATA_NAME, getName()); 01496 data.put(CjdbcNotificationList.DATA_URL, getURL()); 01497 RmiConnector.broadcastNotification(this, type, 01498 CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get(type, 01499 getName()), data); 01500 } 01501 } 01502 01508 public boolean isWriteCanBeEnabled() 01509 { 01510 return writeCanBeEnabled; 01511 } 01512 01518 public void setStateListener(BackendStateListener stateListener) 01519 { 01520 this.stateListener = stateListener; 01521 } 01522 }

CJDBCversion1.0.4に対してTue Oct 12 15:16:00 2004に生成されました。 doxygen 1.3.8