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
00083
00084
00085
00086
00087
00088
00089
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
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
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
00505
00506
00507
00508
00509
00510
00511
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
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
00570
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
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
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
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 {
01114
if (logger.isDebugEnabled())
01115 logger.debug(
Translate.get(
"backend.rewriting.query", sqlQuery));
01116
if (rule.
isStopOnMatch())
01117
break;
01118 }
01119 }
01120
return sqlQuery;
01121 }
01122
01123
01124
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
01378
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
01397
DatabaseBackend newBackend =
new DatabaseBackend(newName, driverPath,
01398 driverClassName, url, writeCanBeEnabled, connectionTestStatement);
01399
01400
01401
01402 newBackend.
setRewritingRules(
this.getRewritingRules());
01403
01404
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
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 }