00001
00025
package org.objectweb.cjdbc.controller.virtualdatabase;
00026
00027
import java.io.Serializable;
00028
import java.sql.SQLException;
00029
import java.util.ArrayList;
00030
import java.util.Hashtable;
00031
import java.util.Map;
00032
00033
import javax.management.NotCompliantMBeanException;
00034
import javax.management.ObjectName;
00035
00036
import org.objectweb.cjdbc.common.exceptions.BackupException;
00037
import org.objectweb.cjdbc.common.exceptions.ExceptionTypes;
00038
import org.objectweb.cjdbc.common.exceptions.OctopusException;
00039
import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException;
00040
import org.objectweb.cjdbc.common.i18n.Translate;
00041
import org.objectweb.cjdbc.common.jmx.JmxConstants;
00042
import org.objectweb.cjdbc.common.jmx.JmxException;
00043
import org.objectweb.cjdbc.common.jmx.mbeans.VirtualDatabaseMBean;
00044
import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList;
00045
import org.objectweb.cjdbc.common.log.Trace;
00046
import org.objectweb.cjdbc.common.shared.BackendState;
00047
import org.objectweb.cjdbc.common.shared.BackupListener;
00048
import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
00049
import org.objectweb.cjdbc.common.sql.SelectRequest;
00050
import org.objectweb.cjdbc.common.sql.StoredProcedure;
00051
import org.objectweb.cjdbc.common.sql.filters.AbstractBlobFilter;
00052
import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema;
00053
import org.objectweb.cjdbc.common.sql.schema.DatabaseTable;
00054
import org.objectweb.cjdbc.common.users.AdminUser;
00055
import org.objectweb.cjdbc.common.users.VirtualDatabaseUser;
00056
import org.objectweb.cjdbc.common.util.Constants;
00057
import org.objectweb.cjdbc.common.util.ReadPrioritaryFIFOWriteLock;
00058
import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00059
import org.objectweb.cjdbc.common.xml.XmlComponent;
00060
import org.objectweb.cjdbc.controller.authentication.AuthenticationManager;
00061
import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00062
import org.objectweb.cjdbc.controller.core.Controller;
00063
import org.objectweb.cjdbc.controller.core.shutdown.VirtualDatabaseShutdownThread;
00064
import org.objectweb.cjdbc.controller.jmx.AbstractStandardMBean;
00065
import org.objectweb.cjdbc.controller.jmx.MBeanServerManager;
00066
import org.objectweb.cjdbc.controller.jmx.RmiConnector;
00067
import org.objectweb.cjdbc.controller.monitoring.SQLMonitoring;
00068
import org.objectweb.cjdbc.controller.recoverylog.AbstractRecoveryLog;
00069
import org.objectweb.cjdbc.controller.recoverylog.BackendRecoveryInfo;
00070
import org.objectweb.cjdbc.controller.recoverylog.JDBCRecoveryLog;
00071
import org.objectweb.cjdbc.controller.requestmanager.RequestManager;
00072
00085 public class VirtualDatabase extends AbstractStandardMBean
00086 implements
00087 Serializable,
00088 VirtualDatabaseMBean,
00089 XmlComponent
00090 {
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00105 protected String
name;
00106
00111 protected AuthenticationManager
authenticationManager;
00112
00114 protected ArrayList
backends;
00115
00117 protected ReadPrioritaryFIFOWriteLock
rwLock;
00118
00120 protected RequestManager
requestManager;
00121
00123 public Trace
logger = null;
00124 protected Trace
requestLogger = null;
00125
00126
00127 private ArrayList
activeThreads =
new ArrayList();
00128
00129 private int idleThreads = 0;
00130
00131 private ArrayList
pendingConnections =
new ArrayList();
00132
00134 protected int maxNbOfConnections;
00135
00137 protected boolean poolConnectionThreads;
00138
00140 protected long maxThreadIdleTime;
00141
00146 protected int minNbOfThreads;
00147
00149 protected int maxNbOfThreads;
00150
00152 protected int currentNbOfThreads;
00153
00155 protected VirtualDatabaseMetaData metadata;
00156
00157 private SQLMonitoring
sqlMonitor = null;
00158
00160 public static final int CHECK_BACKEND_ENABLE = 1;
00162 public static final int CHECK_BACKEND_DISABLE = 0;
00164 public static final int NO_CHECK_BACKEND = -1;
00165
00167 private int sqlShortFormLength;
00168
00170 private AbstractBlobFilter
blobFilter;
00171
00173 Controller
controller;
00174
00176 private String
databaseProductNames =
"C-JDBC";
00177
00179 private boolean shuttingDown =
false;
00180
00181
00182
00201 public VirtualDatabase(Controller controller, String name,
00202
int maxConnections,
boolean pool,
int minThreads,
int maxThreads,
00203
long maxThreadIdleTime,
int sqlShortFormLength,
00204 AbstractBlobFilter blobFilter)
throws NotCompliantMBeanException,
00205
JmxException
00206 {
00207 super(VirtualDatabaseMBean.class);
00208
this.controller =
controller;
00209
this.name =
name;
00210
this.maxNbOfConnections = maxConnections;
00211
this.poolConnectionThreads = pool;
00212
this.minNbOfThreads = minThreads;
00213
this.maxNbOfThreads = maxThreads;
00214
this.maxThreadIdleTime =
maxThreadIdleTime;
00215
this.sqlShortFormLength =
sqlShortFormLength;
00216
this.blobFilter =
blobFilter;
00217
backends =
new ArrayList();
00218
00219 ObjectName objectName =
JmxConstants.getVirtualDbObjectName(
name);
00220
MBeanServerManager.registerMBean(
this, objectName);
00221
00222
rwLock =
new ReadPrioritaryFIFOWriteLock();
00223
logger = Trace.getLogger(
"org.objectweb.cjdbc.controller.virtualdatabase."
00224 +
name);
00225
requestLogger = Trace
00226 .getLogger(
"org.objectweb.cjdbc.controller.virtualdatabase.request."
00227 +
name);
00228 }
00229
00233 public String
getAssociatedString()
00234 {
00235
return "virtualdatabase";
00236 }
00237
00243 public boolean isDistributed()
00244 {
00245
return false;
00246 }
00247
00248
00249
00259 public boolean checkUserAuthentication(String virtualLogin,
00260 String virtualPassword)
00261 {
00262
if (
authenticationManager == null)
00263 {
00264
logger.error(
"No authentification manager defined to check login '"
00265 + virtualLogin +
"'");
00266
return false;
00267 }
00268
else
00269
return authenticationManager.isValidVirtualUser(
new VirtualDatabaseUser(
00270 virtualLogin, virtualPassword));
00271 }
00272
00282 public boolean checkAdminAuthentication(String adminLogin,
00283 String adminPassword)
00284 {
00285
if (
authenticationManager == null)
00286 {
00287
logger.error(
"No authentification manager defined to check admin login '"
00288 + adminLogin +
"'");
00289
return false;
00290 }
00291
else
00292
return authenticationManager.isValidAdminUser(
new AdminUser(adminLogin,
00293 adminPassword));
00294 }
00295
00303 public ControllerResultSet execReadRequest(
SelectRequest request)
00304
throws SQLException
00305 {
00306
if (request == null)
00307 {
00308 String msg =
"Request failed (null read request received)";
00309
logger.warn(msg);
00310
throw new SQLException(msg);
00311 }
00312
00313
try
00314 {
00315
if (
requestLogger.isInfoEnabled())
00316
requestLogger.info(
"S " + request.getTransactionId() +
" "
00317 + request.getSQL());
00318
00319
long start = 0;
00320
if (
sqlMonitor != null)
00321 start = System.currentTimeMillis();
00322
00323
ControllerResultSet rs =
requestManager.execReadRequest(request);
00324
00325
if (
sqlMonitor != null)
00326
sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start);
00327
00328
return rs;
00329 }
00330
catch (SQLException e)
00331 {
00332 String msg =
"Request '" + request.getId() +
"' failed ("
00333 + e.getMessage() +
")";
00334
logger.warn(msg);
00335
if (
sqlMonitor != null)
00336
sqlMonitor.logError(request);
00337
throw e;
00338 }
00339 }
00340
00348 public int execWriteRequest(
AbstractWriteRequest request)
throws SQLException
00349 {
00350
if (request == null)
00351 {
00352 String msg =
"Request failed (null write request received)";
00353
logger.warn(msg);
00354
throw new SQLException(msg);
00355 }
00356
00357
try
00358 {
00359
if (
requestLogger.isInfoEnabled())
00360
requestLogger.info(
"W " + request.getTransactionId() +
" "
00361 + request.getSQL());
00362
00363
long start = 0;
00364
if (
sqlMonitor != null)
00365 start = System.currentTimeMillis();
00366
00367
int result =
requestManager.execWriteRequest(request);
00368
00369
if (
sqlMonitor != null)
00370
sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start);
00371
00372
return result;
00373 }
00374
catch (SQLException e)
00375 {
00376 String msg =
"Request '" + request.getId() +
"' failed ("
00377 + e.getMessage() +
")";
00378
logger.warn(msg);
00379
if (
sqlMonitor != null)
00380
sqlMonitor.logError(request);
00381
throw e;
00382 }
00383 }
00384
00392 public ControllerResultSet execWriteRequestWithKeys(
00393
AbstractWriteRequest request)
throws SQLException
00394 {
00395
if (request == null)
00396 {
00397 String msg =
"Request failed (null write request received)";
00398
logger.warn(msg);
00399
throw new SQLException(msg);
00400 }
00401
00402
try
00403 {
00404
if (
requestLogger.isInfoEnabled())
00405
requestLogger.info(
"W " + request.getTransactionId() +
" "
00406 + request.getSQL());
00407
00408
long start = 0;
00409
if (
sqlMonitor != null)
00410 start = System.currentTimeMillis();
00411
00412
ControllerResultSet result =
requestManager
00413 .execWriteRequestWithKeys(request);
00414
00415
if (
sqlMonitor != null)
00416
sqlMonitor.logRequestTime(request, System.currentTimeMillis() - start);
00417
00418
return result;
00419 }
00420
catch (SQLException e)
00421 {
00422 String msg =
"Request '" + request.getId() +
"' failed ("
00423 + e.getMessage() +
")";
00424
logger.warn(msg);
00425
if (
sqlMonitor != null)
00426
sqlMonitor.logError(request);
00427
throw e;
00428 }
00429 }
00430
00438 public ControllerResultSet execReadStoredProcedure(
StoredProcedure proc)
00439
throws SQLException
00440 {
00441
if (proc == null)
00442 {
00443 String msg =
"Request failed (null stored procedure received)";
00444
logger.warn(msg);
00445
throw new SQLException(msg);
00446 }
00447
00448
try
00449 {
00450
if (
requestLogger.isInfoEnabled())
00451
requestLogger
00452 .info(
"S " + proc.getTransactionId() +
" " + proc.getSQL());
00453
00454
long start = 0;
00455
if (
sqlMonitor != null)
00456 start = System.currentTimeMillis();
00457
00458
ControllerResultSet rs =
requestManager.execReadStoredProcedure(proc);
00459
00460
if (
sqlMonitor != null)
00461
sqlMonitor.logRequestTime(proc, System.currentTimeMillis() - start);
00462
00463
return rs;
00464 }
00465
catch (SQLException e)
00466 {
00467 String msg =
Translate.get(
"loadbalancer.storedprocedure.failed",
00468
new String[]{String.valueOf(proc.getId()), e.getMessage()});
00469
logger.warn(msg);
00470
if (
sqlMonitor != null)
00471
sqlMonitor.logError(proc);
00472
throw e;
00473 }
00474 }
00475
00483 protected int execWriteStoredProcedure(
StoredProcedure proc)
00484
throws SQLException
00485 {
00486
if (proc == null)
00487 {
00488 String msg =
"Request failed (null stored procedure received)";
00489 logger.warn(msg);
00490
throw new SQLException(msg);
00491 }
00492
00493
try
00494 {
00495
if (requestLogger.isInfoEnabled())
00496 requestLogger
00497 .info(
"W " + proc.getTransactionId() +
" " + proc.getSQL());
00498
00499
long start = 0;
00500
if (sqlMonitor != null)
00501 start = System.currentTimeMillis();
00502
00503
int result = requestManager.execWriteStoredProcedure(proc);
00504
00505
if (sqlMonitor != null)
00506 sqlMonitor.logRequestTime(proc, System.currentTimeMillis() - start);
00507
00508
return result;
00509 }
00510
catch (SQLException e)
00511 {
00512 String msg =
Translate.get(
"loadbalancer.storedprocedure.failed",
00513
new String[]{String.valueOf(proc.getId()), e.getMessage()});
00514 logger.warn(msg);
00515
if (sqlMonitor != null)
00516 sqlMonitor.logError(proc);
00517
throw e;
00518 }
00519 }
00520
00521
00522
00533 public long begin(String login)
throws SQLException
00534 {
00535
try
00536 {
00537
long tid = requestManager.begin(login);
00538
if (requestLogger.isInfoEnabled())
00539 requestLogger.info(
"B " + tid);
00540
return tid;
00541 }
00542
catch (SQLException e)
00543 {
00544 String msg =
"Begin failed (" + e.getMessage() +
")";
00545 logger.warn(msg);
00546
throw e;
00547 }
00548 }
00549
00556 public void commit(
long transactionId)
throws SQLException
00557 {
00558
try
00559 {
00560
if (requestLogger.isInfoEnabled())
00561 requestLogger.info(
"C " + transactionId);
00562 requestManager.commit(transactionId);
00563 }
00564
catch (SQLException e)
00565 {
00566 String msg =
"Commit of transaction '" + transactionId +
"' failed ("
00567 + e.getMessage() +
")";
00568 logger.warn(msg);
00569
throw e;
00570 }
00571 }
00572
00579 public void rollback(
long transactionId)
throws SQLException
00580 {
00581
try
00582 {
00583
if (requestLogger.isInfoEnabled())
00584 requestLogger.info(
"R " + transactionId);
00585 requestManager.rollback(transactionId);
00586 }
00587
catch (SQLException e)
00588 {
00589 String msg =
"Rollback of transaction '" + transactionId +
"' failed ("
00590 + e.getMessage() +
")";
00591 logger.warn(msg);
00592
throw e;
00593 }
00594 }
00595
00596
00597
00601 public void backupBackendWithCheckpoint(String backendName,
00602 String checkpointName, ArrayList tables)
throws VirtualDatabaseException
00603 {
00604
try
00605 {
00606
DatabaseBackend db = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
00607 requestManager.backupBackendWithCheckpoint(db, checkpointName, tables, db
00608 .isReadEnabled(),
true, null);
00609 }
00610
catch (SQLException sql)
00611 {
00612
throw new VirtualDatabaseException(sql.getMessage());
00613 }
00614 }
00615
00620 public synchronized void callBackupManager(
boolean backup,
00621 String backendName, String checkpoint, ArrayList tables,
00622
boolean enableAfter,
BackupListener listener)
00623
throws VirtualDatabaseException
00624 {
00625
try
00626 {
00627
DatabaseBackend db = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
00628 requestManager.callBackupManager(backup, db, checkpoint, tables, db
00629 .isReadEnabled(), listener);
00630 }
00631
catch (Exception sql)
00632 {
00633
throw new VirtualDatabaseException(sql.getMessage());
00634 }
00635 }
00636
00637
00638
00645 public void addBackend(
DatabaseBackend db)
throws VirtualDatabaseException
00646 {
00647
this.addBackend(db,
true);
00648 }
00649
00657 public void addBackend(
DatabaseBackend db,
boolean checkForCompliance)
00658
throws VirtualDatabaseException
00659 {
00660
if (db == null)
00661 {
00662 String msg =
"Illegal null database backend in addBackend(DatabaseBackend) method";
00663 logger.error(msg);
00664
throw new VirtualDatabaseException(msg);
00665 }
00666
00667
if (db.isReadEnabled())
00668 {
00669 String msg =
"It is not allowed to add an enabled database.";
00670 logger.error(msg);
00671
throw new VirtualDatabaseException(msg);
00672 }
00673
00674
try
00675 {
00676 rwLock.acquireWrite();
00677 }
00678
catch (InterruptedException e)
00679 {
00680 String msg =
Translate.get(
00681
"loadbalancer.backendlist.acquire.writelock.failed", e);
00682 logger.error(msg);
00683
throw new VirtualDatabaseException(msg);
00684 }
00685
00686
if (backends.indexOf(db) == -1)
00687 {
00688
00689 ArrayList logins = authenticationManager.getVirtualLogins();
00690
VirtualDatabaseUser vdu;
00691 String login;
00692
for (
int i = 0; i < logins.size(); i++)
00693 {
00694 vdu = (
VirtualDatabaseUser) logins.get(i);
00695 login = vdu.
getLogin();
00696
if (db.getConnectionManager(login) == null)
00697
throw new VirtualDatabaseException(
Translate.get(
00698
"backend.missing.connection.manager", login));
00699 }
00700
00701
00702
try
00703 {
00704
if (logger.isDebugEnabled())
00705 logger.debug(
"Checking driver compliance");
00706
if (checkForCompliance)
00707 db.checkDriverCompliance();
00708
00709
00710 }
00711
catch (Exception e)
00712 {
00713 rwLock.releaseWrite();
00714 String msg =
"Error while adding database backend " + db.getName()
00715 +
" (" + e +
")";
00716 logger.warn(msg);
00717
throw new VirtualDatabaseException(msg);
00718 }
00719 db.setSqlShortFormLength(getSQLShortFormLength());
00720 backends.add(db);
00721
00722
00723
if (logger.isDebugEnabled())
00724 logger.debug(
"Backend " + db.getName() +
" added successfully");
00725
00726 rwLock.releaseWrite();
00727
00728
00729
if (
MBeanServerManager.isJmxEnabled())
00730 {
00731
00732 Hashtable data =
new Hashtable();
00733 data.put(
CjdbcNotificationList.DATA_DATABASE,
this.name);
00734 data.put(
CjdbcNotificationList.DATA_DRIVER, db.getDriverClassName());
00735 String checkpoint = db.getLastKnownCheckpoint();
00736 checkpoint = (checkpoint == null) ?
"" : checkpoint;
00737 data.put(
CjdbcNotificationList.DATA_CHECKPOINT, checkpoint);
00738 data.put(
CjdbcNotificationList.DATA_NAME, db.getName());
00739 data.put(
CjdbcNotificationList.DATA_URL, db.getURL());
00740
RmiConnector.broadcastNotification(
this,
00741
CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ADDED,
00742
CjdbcNotificationList.NOTIFICATION_LEVEL_INFO,
Translate.get(
00743
"notification.backend.added", db.getName()), data);
00744
00745
00746 ObjectName objectName =
JmxConstants.getDatabaseBackendObjectName(name,
00747 db.getName());
00748
try
00749 {
00750
MBeanServerManager.registerMBean(db, objectName);
00751 }
00752
catch (
JmxException e1)
00753 {
00754 logger.error(
Translate.get(
00755
"virtualdatabase.fail.register.backend.mbean", db.getName()), e1);
00756 }
00757 }
00758
00759 }
00760
else
00761 {
00762 rwLock.releaseWrite();
00763 String msg =
"Duplicate backend " + db.getURL();
00764 logger.warn(msg);
00765
throw new VirtualDatabaseException(msg);
00766 }
00767
00768 }
00769
00776 public void removeCheckpoint(String checkpointName)
00777
throws VirtualDatabaseException
00778 {
00779
try
00780 {
00781 requestManager.removeCheckpoint(checkpointName);
00782 }
00783
catch (Exception e)
00784 {
00785
throw new VirtualDatabaseException(e.getMessage());
00786 }
00787 }
00788
00792 public void removeBackend(String backend)
throws VirtualDatabaseException
00793 {
00794 removeBackend(getAndCheckBackend(backend, NO_CHECK_BACKEND));
00795 }
00796
00803 public void removeBackend(
DatabaseBackend db)
throws VirtualDatabaseException
00804 {
00805
if (db == null)
00806 {
00807 String msg =
"Illegal null database backend in removeBackend(DatabaseBackend) method";
00808 logger.error(msg);
00809
throw new VirtualDatabaseException(msg);
00810 }
00811
00812
try
00813 {
00814 rwLock.acquireWrite();
00815 }
00816
catch (InterruptedException e)
00817 {
00818 String msg =
Translate.get(
00819
"loadbalancer.backendlist.acquire.writelock.failed", e);
00820 logger.error(msg);
00821
throw new VirtualDatabaseException(msg);
00822 }
00823
00824
00825
int idx = backends.indexOf(db);
00826
if (idx == -1)
00827 {
00828 rwLock.releaseWrite();
00829 String msg =
"Trying to remove a non-existing backend " + db.getName();
00830 logger.warn(msg);
00831
throw new VirtualDatabaseException(msg);
00832 }
00833
00834
if (((
DatabaseBackend) backends.get(idx)).isReadEnabled())
00835 {
00836 rwLock.releaseWrite();
00837 String msg =
"Trying to remove an enabled backend " + db.getName();
00838 logger.error(msg);
00839
throw new VirtualDatabaseException(msg);
00840 }
00841
00842
00843 backends.remove(idx);
00844 rwLock.releaseWrite();
00845
00846
00847
if (
MBeanServerManager.isJmxEnabled())
00848 {
00849
00850 Hashtable data =
new Hashtable();
00851 data.put(
CjdbcNotificationList.DATA_DATABASE,
this.name);
00852 data.put(
CjdbcNotificationList.DATA_DRIVER, db.getDriverClassName());
00853 String checkpoint = db.getLastKnownCheckpoint();
00854 checkpoint = (checkpoint == null) ?
"" : checkpoint;
00855 data.put(
CjdbcNotificationList.DATA_CHECKPOINT, checkpoint);
00856 data.put(
CjdbcNotificationList.DATA_NAME, db.getName());
00857 data.put(
CjdbcNotificationList.DATA_URL, db.getURL());
00858
RmiConnector.broadcastNotification(
this,
00859
CjdbcNotificationList.VIRTUALDATABASE_BACKEND_REMOVED,
00860
CjdbcNotificationList.NOTIFICATION_LEVEL_INFO,
Translate.get(
00861
"notification.backend.removed", db.getName()), data);
00862
00863
00864 ObjectName objectName =
JmxConstants.getDatabaseBackendObjectName(name,
00865 db.getName());
00866
try
00867 {
00868
MBeanServerManager.unregister(objectName);
00869 }
00870
catch (
JmxException e1)
00871 {
00872 logger.error(
Translate.get(
00873
"virtualdatabase.fail.unregister.backend.mbean", db.getName()), e1);
00874 }
00875 }
00876
00877
if (logger.isDebugEnabled())
00878 logger.debug(
"Backend " + db.getName() +
" removed successfully");
00879 }
00880
00884 public ArrayList viewCheckpointNames()
00885 {
00886
try
00887 {
00888
AbstractRecoveryLog recoveryLog = requestManager.getRecoveryLog();
00889
if (recoveryLog == null)
00890
return new ArrayList();
00891
else
00892
return recoveryLog.
getCheckpointNames();
00893 }
00894
catch (SQLException e)
00895 {
00896
return new ArrayList();
00897 }
00898 }
00899
00903 public void enableBackend(String backendName)
throws VirtualDatabaseException
00904 {
00905
00906
try
00907 {
00908
DatabaseBackend backend = getAndCheckBackend(backendName,
00909 CHECK_BACKEND_ENABLE);
00910
00911 requestManager.enableBackend(backend);
00912
00913
00914
if (databaseProductNames.indexOf(backend.
getDatabaseProductName()) == -1)
00915 databaseProductNames +=
"," + backend.
getDatabaseProductName();
00916
00917
00918
if (
MBeanServerManager.isJmxEnabled())
00919 {
00920 Hashtable data =
new Hashtable();
00921 data.put(
"driver", backend.
getDriverClassName());
00922 String checkpoint = backend.
getLastKnownCheckpoint();
00923 checkpoint = (checkpoint == null) ?
"" : checkpoint;
00924 data.put(
"checkpoint", checkpoint);
00925 data.put(
"name", backend.
getName());
00926 data.put(
"url", backend.
getURL());
00927
RmiConnector.broadcastNotification(
this,
00928
CjdbcNotificationList.VIRTUALDATABASE_BACKEND_ENABLED,
00929
CjdbcNotificationList.NOTIFICATION_LEVEL_INFO,
Translate.get(
00930
"notification.backend.enabled", backend.
getName()), data);
00931 }
00932 }
00933
catch (Exception e)
00934 {
00935 e.printStackTrace();
00936
throw new VirtualDatabaseException(e.getMessage());
00937 }
00938 }
00939
00943 public void enableBackendFromCheckpoint(String backendName,
00944 String checkpointName)
throws VirtualDatabaseException
00945 {
00946
00947
try
00948 {
00949
DatabaseBackend backend = getAndCheckBackend(backendName,
00950 CHECK_BACKEND_ENABLE);
00951 requestManager.enableBackendFromCheckpoint(backend, checkpointName);
00952
00953
00954
if (databaseProductNames.indexOf(backend.
getDatabaseProductName()) == -1)
00955 databaseProductNames +=
"," + backend.
getDatabaseProductName();
00956 }
00957
catch (Exception e)
00958 {
00959
throw new VirtualDatabaseException(
00960
"Failed to enable backend from checkpoint: " + e);
00961 }
00962 }
00963
00967 public void enableBackendFromLastCheckpoint(String backendName)
00968
throws VirtualDatabaseException
00969 {
00970
DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
00971 String checkpoint = backend.
getLastKnownCheckpoint();
00972
if (checkpoint == null)
00973
throw new VirtualDatabaseException(
"No last checkpoint for backend:"
00974 + backendName);
00975
else
00976 {
00977
if (logger.isDebugEnabled())
00978 logger.debug(
"Enabling backend:" + backendName
00979 +
" with its last checkpoint:" + backend.
getLastKnownCheckpoint());
00980 }
00981 enableBackendFromCheckpoint(backendName, backend.
getLastKnownCheckpoint());
00982 }
00983
00997 public DatabaseBackend getAndCheckBackend(String backendName,
int testEnable)
00998
throws VirtualDatabaseException
00999 {
01000
try
01001 {
01002 acquireReadLockBackendLists();
01003 }
01004
catch (InterruptedException e)
01005 {
01006 String msg =
"Unable to acquire read lock on backend list in getAndCheckBackend ("
01007 + e +
")";
01008 logger.error(msg);
01009
throw new VirtualDatabaseException(msg);
01010 }
01011
01012
01013
int size = backends.size();
01014
DatabaseBackend b = null;
01015
for (
int i = 0; i < size; i++)
01016 {
01017 b = (
DatabaseBackend) backends.get(i);
01018
if (b.
getName().equals(backendName))
01019
break;
01020
else
01021 b = null;
01022 }
01023
01024
if (b == null)
01025 {
01026 releaseReadLockBackendLists();
01027 String msg =
"Trying to access a non-existing backend " + backendName;
01028 logger.warn(msg);
01029
throw new VirtualDatabaseException(msg);
01030 }
01031
01032
01033
switch (testEnable)
01034 {
01035
case NO_CHECK_BACKEND :
01036
break;
01037
case CHECK_BACKEND_DISABLE :
01038
if (!b.
isReadEnabled())
01039 {
01040 releaseReadLockBackendLists();
01041 String msg =
"Backend " + backendName +
" is already disabled";
01042 logger.warn(msg);
01043
throw new VirtualDatabaseException(msg);
01044 }
01045
break;
01046
case CHECK_BACKEND_ENABLE :
01047
if (b.
isReadEnabled())
01048 {
01049 releaseReadLockBackendLists();
01050 String msg =
"Backend " + backendName +
" is already enabled";
01051 logger.warn(msg);
01052
throw new VirtualDatabaseException(msg);
01053 }
01054
break;
01055
default :
01056 releaseReadLockBackendLists();
01057 String msg =
"Unexpected parameter in getAndCheckBackend(...)";
01058 logger.error(msg);
01059
throw new VirtualDatabaseException(msg);
01060 }
01061
01062 releaseReadLockBackendLists();
01063
01064
if (testEnable == CHECK_BACKEND_ENABLE)
01065 {
01066
01067
try
01068 {
01069
if (logger.isDebugEnabled())
01070 logger.debug(
"Initializing connections for backend " + b.
getName());
01071 b.
initializeConnections();
01072
01073 b.
checkDriverCompliance();
01074
01075
if (logger.isDebugEnabled())
01076 logger.debug(
"Checking schema for backend " + b.
getName());
01077 b.
checkDatabaseSchema();
01078
01079
DatabaseSchema backendSchema = b.
getDatabaseSchema();
01080
01081
if (backendSchema != null)
01082 requestManager.mergeDatabaseSchema(backendSchema);
01083
else
01084 logger.warn(
"Backend " + b.
getName() +
" has no defined schema.");
01085 }
01086
catch (SQLException e)
01087 {
01088 String msg =
"Error while initalizing database backend " + b.
getName()
01089 +
" (" + e +
")";
01090 logger.warn(msg,e);
01091
throw new VirtualDatabaseException(msg);
01092 }
01093 }
01094
01095
return b;
01096 }
01097
01101 public void disableBackend(String backendName)
01102
throws VirtualDatabaseException
01103 {
01104
try
01105 {
01106
DatabaseBackend db = getAndCheckBackend(backendName,
01107 CHECK_BACKEND_DISABLE);
01108 requestManager.disableBackend(db);
01109 requestManager.setDatabaseSchema(
01110 getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames(),
01111
false);
01112
01113
01114
if (
MBeanServerManager.isJmxEnabled())
01115 {
01116 Hashtable data =
new Hashtable();
01117 data.put(
"driver", db.
getDriverClassName());
01118 String checkpoint = db.
getLastKnownCheckpoint();
01119 checkpoint = (checkpoint == null) ?
"" : checkpoint;
01120 data.put(
"checkpoint", checkpoint);
01121 data.put(
"name", db.
getName());
01122 data.put(
"url", db.
getURL());
01123
RmiConnector.broadcastNotification(
this,
01124
CjdbcNotificationList.VIRTUALDATABASE_BACKEND_DISABLED,
01125
CjdbcNotificationList.NOTIFICATION_LEVEL_INFO,
Translate.get(
01126
"notification.backend.disabled", db.
getName()), data);
01127 }
01128 }
01129
catch (Exception e)
01130 {
01131 logger.error(
"An error occured while disabling backend " + backendName
01132 +
" (" + e +
")");
01133
throw new VirtualDatabaseException(e.getMessage());
01134 }
01135 }
01136
01145 public void disableAllBackend() throws
VirtualDatabaseException
01146 {
01147
try
01148 {
01149
int size =
this.backends.size();
01150
DatabaseBackend dbe;
01151
for (
int i = 0; i < size; i++)
01152 {
01153 dbe = (
DatabaseBackend) backends.get(i);
01154
if (dbe.
isReadEnabled())
01155 requestManager.disableBackend(getAndCheckBackend(dbe.
getName(),
01156 CHECK_BACKEND_DISABLE));
01157 }
01158 }
01159
catch (Exception e)
01160 {
01161
throw new VirtualDatabaseException(e.getMessage());
01162 }
01163 }
01164
01170 public void enableAllBackend() throws
VirtualDatabaseException
01171 {
01172
try
01173 {
01174
int size =
this.backends.size();
01175
DatabaseBackend dbe;
01176
for (
int i = 0; i < size; i++)
01177 {
01178 dbe = (
DatabaseBackend) backends.get(i);
01179
if (!dbe.
isReadEnabled())
01180 enableBackend(((
DatabaseBackend) backends.get(i)).getName());
01181 }
01182 }
01183
catch (Exception e)
01184 {
01185 logger.error(e);
01186
throw new VirtualDatabaseException(e.getMessage());
01187 }
01188 }
01189
01196 public void enableAllBackend(String checkpoint)
01197
throws VirtualDatabaseException
01198 {
01199
if (checkpoint == null || checkpoint.equals(
""))
01200 enableAllBackend();
01201
else
01202 {
01203
try
01204 {
01205
int size =
this.backends.size();
01206
DatabaseBackend dbe;
01207
for (
int i = 0; i < size; i++)
01208 {
01209 dbe = (
DatabaseBackend) backends.get(i);
01210
if (!dbe.
isReadEnabled())
01211 {
01212
if (checkpoint == null || checkpoint.equals(
""))
01213 enableBackend(((
DatabaseBackend) backends.get(i)).getName());
01214
else
01215 enableBackendFromCheckpoint(((
DatabaseBackend) backends.get(i))
01216 .getName(), checkpoint);
01217 }
01218 }
01219 }
01220
catch (Exception e)
01221 {
01222
throw new VirtualDatabaseException(e.getMessage());
01223 }
01224 }
01225 }
01226
01230 public void enableAllBackendsFromRecovery(String checkpoint)
01231
throws VirtualDatabaseException
01232 {
01233
AbstractRecoveryLog log = requestManager.getRecoveryLog();
01234
01235
if (log == null)
01236 {
01237 enableAllBackend();
01238 }
01239
else
01240 {
01241
try
01242 {
01243
int size =
this.backends.size();
01244
DatabaseBackend dbe;
01245 String backendName;
01246
BackendRecoveryInfo info;
01247
for (
int i = 0; i < size; i++)
01248 {
01249 dbe = (
DatabaseBackend) backends.get(i);
01250 backendName = dbe.
getName();
01251 info = log.
getBackendInfo(name, backendName);
01252
if (info.
getBackendState() ==
BackendState.DISABLED)
01253
continue;
01254
if (!dbe.
isReadEnabled())
01255 {
01256
if (checkpoint == null || checkpoint.equals(
""))
01257 enableBackend(dbe.
getName());
01258
else
01259 enableBackendFromCheckpoint(dbe.
getName(), checkpoint);
01260 }
01261 }
01262 }
01263
catch (Exception e)
01264 {
01265
throw new VirtualDatabaseException(e.getMessage());
01266 }
01267 }
01268
01269 }
01270
01274 public void disableBackendForCheckpoint(String backendName,
01275 String checkpointName)
throws VirtualDatabaseException
01276 {
01277
try
01278 {
01279 requestManager.disableBackendForCheckpoint(getAndCheckBackend(
01280 backendName, CHECK_BACKEND_DISABLE), checkpointName);
01281 requestManager.setDatabaseSchema(
01282 getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames(),
01283
false);
01284 }
01285
catch (Exception e)
01286 {
01287 logger.error(
"An error occured while disabling backend " + backendName
01288 +
" (" + e +
")");
01289
throw new VirtualDatabaseException(e.getMessage());
01290 }
01291 }
01292
01300 public final void acquireReadLockBackendLists() throws InterruptedException
01301 {
01302 rwLock.acquireRead();
01303 }
01304
01310 public final void releaseReadLockBackendLists()
01311 {
01312 rwLock.releaseRead();
01313 }
01314
01315
01316
01322 public AuthenticationManager getAuthenticationManager()
01323 {
01324
return authenticationManager;
01325 }
01326
01333 public void setAuthenticationManager(
01334 AuthenticationManager authenticationManager)
01335 {
01336
this.authenticationManager = authenticationManager;
01337 }
01338
01344 public ArrayList getBackends()
01345 {
01346
return backends;
01347 }
01348
01352 public ArrayList getAllBackendNames() throws
VirtualDatabaseException
01353 {
01354
try
01355 {
01356 acquireReadLockBackendLists();
01357 }
01358
catch (InterruptedException e)
01359 {
01360 String msg =
"Unable to acquire read lock on backend list in getAllBackendNames ("
01361 + e +
")";
01362 logger.error(msg);
01363
throw new VirtualDatabaseException(msg);
01364 }
01365
01366
int size = backends.size();
01367 ArrayList result =
new ArrayList();
01368
for (
int i = 0; i < size; i++)
01369 {
01370 result.add(((
DatabaseBackend) backends.get(i)).getName());
01371 }
01372
01373 releaseReadLockBackendLists();
01374
return result;
01375 }
01376
01385 public String getDatabaseName()
01386 {
01387
return name;
01388 }
01389
01393 public String getDatabaseProductName()
01394 {
01395
return databaseProductNames;
01396 }
01397
01404 public int getSQLShortFormLength()
01405 {
01406
return sqlShortFormLength;
01407 }
01408
01413 public VirtualDatabaseMetaData getMetaData()
01414 {
01415
if (metadata == null)
01416 {
01417 metadata =
new VirtualDatabaseMetaData(
this);
01418 }
01419
return metadata;
01420 }
01421
01429 public DatabaseSchema getDatabaseSchemaFromActiveBackendsAndRefreshDatabaseProductNames()
01430 throws SQLException
01431 {
01432
try
01433 {
01434 acquireReadLockBackendLists();
01435 }
01436
catch (InterruptedException e)
01437 {
01438 String msg =
"Unable to acquire read lock on backend list in getDatabaseSchemaFromActiveBackends ("
01439 + e +
")";
01440 logger.error(msg);
01441
throw new SQLException(msg);
01442 }
01443
01444
int size = backends.size();
01445
DatabaseSchema schema = null;
01446
DatabaseBackend b = null;
01447 String dbProductNames =
"C-JDBC";
01448
for (
int i = 0; i < size; i++)
01449 {
01450 b = (
DatabaseBackend) backends.get(i);
01451
if (b.
isReadEnabled())
01452 {
01453
if (schema == null)
01454 schema = b.
getDatabaseSchema();
01455
else
01456 schema.
mergeSchema(b.
getDatabaseSchema());
01457 }
01458
01459
01460
if (dbProductNames.indexOf(b.
getDatabaseProductName()) == -1)
01461 dbProductNames +=
"," + b.
getDatabaseProductName();
01462 }
01463
01464 releaseReadLockBackendLists();
01465 databaseProductNames = dbProductNames;
01466 logger.debug(
"getDatabaseSchemaFromActiveBackends - end");
01467
if (requestManager.getRecoveryLog() != null)
01468 {
01469
try
01470 {
01471
JDBCRecoveryLog log = (
JDBCRecoveryLog) requestManager.getRecoveryLog();
01472
01473
if (schema.
hasTable(log.
getBackendTableName()))
01474 schema.
removeTable(
new DatabaseTable(log.
getBackendTableName()));
01475
if (schema.
hasTable(log.
getCheckpointTableName()))
01476 schema.
removeTable(
new DatabaseTable(log.
getCheckpointTableName()));
01477
if (schema.
hasTable(log.
getLogTableName()))
01478 schema.
removeTable(
new DatabaseTable(log.
getLogTableName()));
01479 }
01480
catch (RuntimeException ignore)
01481 {
01482
01483 }
01484 }
01485
return schema;
01486 }
01487
01496 public void setDatabaseSchema(
DatabaseSchema schema,
boolean isStatic)
01497 {
01498
if (requestManager != null)
01499 requestManager.setDatabaseSchema(schema, isStatic);
01500
else
01501 logger
01502 .warn(
"Unable to set database schema, no request manager has been defined.");
01503 }
01504
01510 public RequestManager getRequestManager()
01511 {
01512
return requestManager;
01513 }
01514
01520 public void setRequestManager(RequestManager requestManager)
01521 {
01522
this.requestManager = requestManager;
01523 }
01524
01530 public String getVirtualDatabaseName()
01531 {
01532
return name;
01533 }
01534
01541 public SQLMonitoring getSQLMonitor()
01542 {
01543
return sqlMonitor;
01544 }
01545
01551 public void setSQLMonitor(SQLMonitoring sqlMonitor)
01552 {
01553
this.sqlMonitor = sqlMonitor;
01554 }
01555
01562 public boolean equals(Object other)
01563 {
01564
if ((other == null) || (!(other instanceof
VirtualDatabase)))
01565
return false;
01566
else
01567 {
01568
VirtualDatabase db = (
VirtualDatabase) other;
01569
return name.equals(db.
getDatabaseName());
01570 }
01571 }
01572
01578 public String getXml()
01579 {
01580 StringBuffer info =
new StringBuffer();
01581 info.append(
"<C-JDBC>");
01582 info.append(
"<" +
DatabasesXmlTags.ELT_VirtualDatabase +
" "
01583 +
DatabasesXmlTags.ATT_name +
"=\"" +
this.getName() +
"\" "
01584 +
DatabasesXmlTags.ATT_maxNbOfConnections +
"=\""
01585 +
this.getMaxNbOfConnections() +
"\" "
01586 +
DatabasesXmlTags.ATT_poolThreads +
"=\""
01587 +
this.isPoolConnectionThreads() +
"\" "
01588 +
DatabasesXmlTags.ATT_minNbOfThreads +
"=\""
01589 +
this.getMinNbOfThreads() +
"\" "
01590 +
DatabasesXmlTags.ATT_maxNbOfThreads +
"=\""
01591 +
this.getMaxNbOfThreads() +
"\" "
01592 +
DatabasesXmlTags.ATT_maxThreadIdleTime +
"=\""
01593 +
this.getMaxThreadIdleTime() / 1000 +
"\" "
01594 +
DatabasesXmlTags.ATT_sqlDumpLength +
"=\"" +
this.sqlShortFormLength
01595 +
"\" " +
DatabasesXmlTags.ATT_blobEncodingMethod +
"=\""
01596 +
this.blobFilter.getXml() +
"\">");
01597
01598 info.append(getDistributionXml());
01599
01600
if (
this.getSQLMonitor() != null)
01601 info.append(sqlMonitor.getXml());
01602
01603 info.append(requestManager.getBackupManager().getXml());
01604
01605
if (
this.getAuthenticationManager() != null)
01606 info.append(authenticationManager.getXml());
01607
01608
try
01609 {
01610 acquireReadLockBackendLists();
01611
int size = backends.size();
01612
for (
int i = 0; i < size; i++)
01613 info.append(((
DatabaseBackend) backends.get(i)).getXml());
01614 releaseReadLockBackendLists();
01615 }
01616
catch (InterruptedException e)
01617 {
01618 logger.error(
Translate.get(
"virtualdatabase.fail.read.lock", e));
01619 }
01620
if (requestManager != null)
01621 info.append(requestManager.getXml());
01622 info.append(
"</" +
DatabasesXmlTags.ELT_VirtualDatabase +
">");
01623 info.append(
"</C-JDBC>");
01624
return info.toString();
01625 }
01626
01632 protected String getDistributionXml()
01633 {
01634
return "";
01635 }
01636
01640 public String getBackendInformation(String backendName)
01641
throws VirtualDatabaseException
01642 {
01643
try
01644 {
01645 acquireReadLockBackendLists();
01646 }
01647
catch (InterruptedException e)
01648 {
01649 String msg =
"Unable to acquire read lock on backend list in getBackendInformation ("
01650 + e +
")";
01651 logger.error(msg);
01652
throw new VirtualDatabaseException(msg);
01653 }
01654
01655
01656
int size = backends.size();
01657
DatabaseBackend b = null;
01658
for (
int i = 0; i < size; i++)
01659 {
01660 b = (
DatabaseBackend) backends.get(i);
01661
if (b.
getName().equals(backendName))
01662
break;
01663
else
01664 b = null;
01665 }
01666
01667
if (b == null)
01668 {
01669 releaseReadLockBackendLists();
01670 String msg =
"Backend " + backendName +
" does not exists.";
01671 logger.warn(msg);
01672
throw new VirtualDatabaseException(msg);
01673 }
01674
01675 releaseReadLockBackendLists();
01676
return b.
getXml();
01677 }
01678
01680
01682
01688 public String getName()
01689 {
01690
return name;
01691 }
01692
01698 public int getCurrentNbOfThreads()
01699 {
01700
return currentNbOfThreads;
01701 }
01702
01706 public void addCurrentNbOfThread()
01707 {
01708 currentNbOfThreads++;
01709 }
01710
01715 public void removeCurrentNbOfThread()
01716 {
01717 currentNbOfThreads--;
01718 }
01719
01725 public int getMinNbOfThreads()
01726 {
01727
return minNbOfThreads;
01728 }
01729
01735 public boolean isPoolConnectionThreads()
01736 {
01737
return poolConnectionThreads;
01738 }
01739
01745 public void setMinNbOfThreads(
int minNbOfThreads)
01746 {
01747
this.minNbOfThreads = minNbOfThreads;
01748 }
01749
01755 public void setPoolConnectionThreads(
boolean poolConnectionThreads)
01756 {
01757
this.poolConnectionThreads = poolConnectionThreads;
01758 }
01759
01765 public long getMaxThreadIdleTime()
01766 {
01767
return maxThreadIdleTime;
01768 }
01769
01775 public void setMaxThreadIdleTime(
long maxThreadIdleTime)
01776 {
01777
this.maxThreadIdleTime = maxThreadIdleTime;
01778 }
01779
01785 public int getMaxNbOfConnections()
01786 {
01787
return maxNbOfConnections;
01788 }
01789
01795 public int getMaxNbOfThreads()
01796 {
01797
return maxNbOfThreads;
01798 }
01799
01805 public ArrayList getPendingConnections()
01806 {
01807
return pendingConnections;
01808 }
01809
01815 public void setMaxNbOfConnections(
int maxNbOfConnections)
01816 {
01817
this.maxNbOfConnections = maxNbOfConnections;
01818 }
01819
01825 public void setMaxNbOfThreads(
int maxNbOfThreads)
01826 {
01827
this.maxNbOfThreads = maxNbOfThreads;
01828 }
01829
01835 public ArrayList getActiveThreads()
01836 {
01837
return activeThreads;
01838 }
01839
01843 public String[] viewBackendInformation(String backendName)
01844
throws VirtualDatabaseException
01845 {
01846
DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
01847
return backend.
getBackendData();
01848 }
01849
01854 public void addIdleThread()
01855 {
01856 idleThreads++;
01857 }
01858
01863 public void removeIdleThread()
01864 {
01865 idleThreads--;
01866 }
01867
01874 public int getIdleThreads()
01875 {
01876
return idleThreads;
01877 }
01878
01882 public ArrayList viewAllBackendNames() throws
VirtualDatabaseException
01883 {
01884
return this.getAllBackendNames();
01885 }
01886
01893 public ArrayList viewAllClientNames()
01894 {
01895 ArrayList list =
this.getActiveThreads();
01896
int size = list.size();
01897 ArrayList clients =
new ArrayList(size);
01898
for (
int i = 0; i < list.size(); i++)
01899 clients.add(((
VirtualDatabaseWorkerThread) list.get(i)).getUser());
01900
return clients;
01901 }
01902
01906 public void disableAllBackendForCheckpoint(String checkpoint)
01907
throws VirtualDatabaseException
01908 {
01909
if (checkpoint == null)
01910 {
01911 disableAllBackend();
01912
return;
01913 }
01914
01915
try
01916 {
01917
this.acquireReadLockBackendLists();
01918 requestManager.disableBackendsForCheckpoint(backends, checkpoint);
01919
this.releaseReadLockBackendLists();
01920 }
01921
catch (Exception e)
01922 {
01923
throw new VirtualDatabaseException(e.getMessage());
01924 }
01925 }
01926
01927
01928
01935 public void shutdown(
int level)
01936 {
01937
if (shuttingDown)
01938
return;
01939 shuttingDown =
true;
01940
VirtualDatabaseShutdownThread vdst =
new VirtualDatabaseShutdownThread(
01941
this, level);
01942
new Thread(vdst.
getShutdownGroup(), vdst,
"VirtualDatabase Shutdown Thread")
01943 .start();
01944 }
01945
01951 public void shutdown() throws
VirtualDatabaseException
01952 {
01953 shutdown(
Constants.CONTROLLER_SHUTDOWN_FAST);
01954 }
01955
01961 public void setBlobFilter(AbstractBlobFilter filter)
01962 {
01963
this.blobFilter = filter;
01964 }
01965
01971 public AbstractBlobFilter getBlobFilter()
01972 {
01973
return blobFilter;
01974 }
01975
01979 public void setBackendLastKnownCheckpoint(String backendName,
01980 String checkpoint)
throws VirtualDatabaseException
01981 {
01982
AbstractRecoveryLog log = requestManager.getRecoveryLog();
01983
DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
01984
if (log == null)
01985
throw new VirtualDatabaseException(
ExceptionTypes.NO_RECOVERY_LOG);
01986
else
01987 {
01988
if (!backend.
isDisabled())
01989
throw new VirtualDatabaseException(
01990
"Cannot setLastKnownCheckpoint on a non-disabled backend");
01991
else
01992 {
01993
try
01994 {
01995 log.
storeBackendInfo(name, backendName, checkpoint, backend
01996 .getStateValue());
01997 backend.
setLastKnownCheckpoint(checkpoint);
01998 }
01999
catch (SQLException e)
02000 {
02001
throw new VirtualDatabaseException(
02002
"Failed to store recovery info for backend:" + backendName);
02003 }
02004 }
02005 }
02006
02007 }
02008
02012 public String getBackendState(String backendName)
02013
throws VirtualDatabaseException
02014 {
02015
DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
02016
return backend.
getState();
02017 }
02018
02022 public String viewOwningController()
02023 {
02024
return controller.getJmxName();
02025 }
02026
02031 public void restoreBackendFromBackupCheckpoint(String databaseBackendName,
02032 String checkpointName)
throws VirtualDatabaseException,
BackupException,
02033
OctopusException
02034 {
02035
DatabaseBackend backend = getAndCheckBackend(databaseBackendName,
02036 NO_CHECK_BACKEND);
02037
02038
02039 requestManager.restoreBackendFromBackupCheckpoint(backend, checkpointName,
02040
true, null);
02041 }
02042
02046 public void storeBackendsInfo()
02047 {
02048 requestManager.storeBackendsInfo(
this.name, getBackends());
02049 }
02050
02054 public boolean hasRecoveryLog()
02055 {
02056
AbstractRecoveryLog log = requestManager.getRecoveryLog();
02057
if (log == null)
02058
return false;
02059
else
02060
return true;
02061 }
02062
02067 public void replicateBackend(String backendName, String newBackendName,
02068 Map parameters)
throws VirtualDatabaseException
02069 {
02070
02071
DatabaseBackend backend = getAndCheckBackend(backendName, NO_CHECK_BACKEND);
02072
DatabaseBackend newBackend = null;
02073
02074
02075
try
02076 {
02077 newBackend = backend.
copy(newBackendName, parameters);
02078 }
02079
catch (Exception e)
02080 {
02081 String msg =
Translate.get(
"virtualdatabase.fail.backend.copy");
02082 logger.warn(msg, e);
02083
throw new VirtualDatabaseException(msg);
02084 }
02085
02086
02087 addBackend(newBackend);
02088 }
02089
02093 public String[][] retrieveBackendsData() throws VirtualDatabaseException
02094 {
02095
try
02096 {
02097 acquireReadLockBackendLists();
02098 }
02099
catch (InterruptedException e)
02100 {
02101 String msg =
Translate.get(
"virtualdatabase.fail.read.lock", e);
02102
throw new VirtualDatabaseException(msg);
02103 }
02104 ArrayList backends =
this.getBackends();
02105
int backendListSize = backends.size();
02106 String[][] data =
new String[backendListSize][];
02107
for (
int i = 0; i < backendListSize; i++)
02108 {
02109 data[i] = ((
DatabaseBackend) backends.get(i)).getBackendData();
02110 }
02111 releaseReadLockBackendLists();
02112
return data;
02113 }
02114
02118 public String[] viewControllerList()
02119 {
02120
return new String[]{viewOwningController()};
02121 }
02122
02126 public Hashtable viewGroupBackends() throws VirtualDatabaseException
02127 {
02128 Hashtable map =
new Hashtable();
02129 map.put(controller.getJmxName(), viewAllBackendNames());
02130
return map;
02131 }
02132
02137 public void transferBackend(String backend, String controllerDestination)
02138
throws VirtualDatabaseException
02139 {
02140
throw new VirtualDatabaseException(
"Cannot transfer backend to controller:"
02141 + controllerDestination +
" because database is not distributed");
02142 }
02143 }