00001
00025
package org.objectweb.cjdbc.controller.virtualdatabase;
00026
00027
import java.io.Serializable;
00028
import java.net.URL;
00029
import java.sql.SQLException;
00030
import java.util.ArrayList;
00031
import java.util.HashMap;
00032
import java.util.Hashtable;
00033
import java.util.Iterator;
00034
import java.util.Vector;
00035
import java.util.Map.Entry;
00036
00037
import javax.management.NotCompliantMBeanException;
00038
00039
import org.dom4j.DocumentException;
00040
import org.jgroups.Address;
00041
import org.jgroups.JChannel;
00042
import org.jgroups.MembershipListener;
00043
import org.jgroups.Message;
00044
import org.jgroups.MessageListener;
00045
import org.jgroups.View;
00046
import org.jgroups.blocks.GroupRequest;
00047
import org.jgroups.blocks.MessageDispatcher;
00048
import org.jgroups.blocks.RequestHandler;
00049
import org.jgroups.util.RspList;
00050
import org.objectweb.cjdbc.common.exceptions.ControllerException;
00051
import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException;
00052
import org.objectweb.cjdbc.common.i18n.Translate;
00053
import org.objectweb.cjdbc.common.jmx.JmxException;
00054
import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList;
00055
import org.objectweb.cjdbc.common.shared.BackendInfo;
00056
import org.objectweb.cjdbc.common.sql.filters.AbstractBlobFilter;
00057
import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00058
import org.objectweb.cjdbc.controller.authentication.AuthenticationManager;
00059
import org.objectweb.cjdbc.controller.backend.BackendRecoveryPolicy;
00060
import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
00061
import org.objectweb.cjdbc.controller.core.Controller;
00062
import org.objectweb.cjdbc.controller.jmx.MBeanServerManager;
00063
import org.objectweb.cjdbc.controller.jmx.RmiConnector;
00064
import org.objectweb.cjdbc.controller.requestmanager.RequestManager;
00065
import org.objectweb.cjdbc.controller.requestmanager.distributed.DistributedRequestManager;
00066
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.BackendStatus;
00067
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.BackendTransfer;
00068
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.CJDBCGroupMessage;
00069
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.Commit;
00070
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.ControllerName;
00071
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.DistributedRequest;
00072
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.EnableBackend;
00073
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.Rollback;
00074
import org.objectweb.cjdbc.controller.virtualdatabase.protocol.VirtualDatabaseConfiguration;
00075
00084 public class DistributedVirtualDatabase extends VirtualDatabase
00085 implements
00086 RequestHandler,
00087 MessageListener,
00088 MembershipListener
00089 {
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00105 private String
groupName = null;
00107 private Hashtable
controllersMap;
00109 private HashMap
backendRecoveryPolicy;
00111 private Hashtable
backendsPerController;
00112
00114 private JChannel
channel = null;
00116 private MessageDispatcher
dispatcher;
00117 private View
currentView = null;
00118 private Vector
allMemberButUs = null;
00119
00120
00121
00122
00123
00143 public DistributedVirtualDatabase(
Controller controller, String name,
00144 String groupName,
int maxConnections,
boolean pool,
int minThreads,
00145
int maxThreads,
long maxThreadIdleTime,
int sqlShortFormLength,
00146
AbstractBlobFilter blobFilter)
throws NotCompliantMBeanException,
00147
JmxException
00148 {
00149 super(controller, name, maxConnections, pool, minThreads, maxThreads,
00150 maxThreadIdleTime, sqlShortFormLength, blobFilter);
00151
00152
this.groupName =
groupName;
00153
backendRecoveryPolicy =
new HashMap();
00154
backendsPerController =
new Hashtable();
00155
controllersMap =
new Hashtable();
00156 }
00157
00163 protected void finalize() throws Throwable
00164 {
00165
quitChannel();
00166 super.finalize();
00167 }
00168
00172 public void addBackend(
DatabaseBackend db)
throws VirtualDatabaseException
00173 {
00174
00175 super.addBackend(db);
00176
00177
00178
if(
allMemberButUs!=null)
00179
broadcastBackendInformation(
allMemberButUs);
00180 }
00181
00185 public void quitChannel()
00186 {
00187
if (
channel != null)
00188 {
00189
channel.close();
00190 }
00191 }
00192
00198 public String
getControllerName()
00199 {
00200
return controller.
getName();
00201 }
00202
00209 public String
getGroupName()
00210 {
00211
return groupName;
00212 }
00213
00219 public void setGroupName(String groupName)
00220 {
00221
this.groupName = groupName;
00222 }
00223
00229 public void addBackendRecoveryPolicy(
BackendRecoveryPolicy policy)
00230 {
00231
backendRecoveryPolicy.put(policy.
getBackendName(), policy);
00232 }
00233
00239 public void setRequestManager(
RequestManager requestManager)
00240 {
00241
if (!(requestManager instanceof
DistributedRequestManager))
00242
throw new RuntimeException(
00243
"A distributed virtual database can only work with a distributed request manager.");
00244
this.requestManager = requestManager;
00245 }
00246
00247
00248
00249
00250
00257 public void joinGroup() throws Exception
00258 {
00259
try
00260 {
00261
00262 URL jgroupConfigFile =
DistributedVirtualDatabase.class
00263 .getResource(
"/jgroups.xml");
00264
if (jgroupConfigFile == null)
00265 logger.
warn(
Translate
00266 .get(
"virtualdatabase.distributed.jgroups.xml.not.found"));
00267
else
00268 logger.
info(
Translate.get(
"virtualdatabase.distributed.jgroups.using",
00269 jgroupConfigFile.toString()));
00270
channel =
new JChannel(jgroupConfigFile);
00271
if (logger.
isDebugEnabled())
00272 logger.
debug(
"Group communication channel is configured as follows: "
00273 +
channel.getProperties());
00274
00275
00276
channel.connect(
groupName);
00277
dispatcher =
new MessageDispatcher(
channel
00278
00279
00280
00281 ,
this
00282 ,
this
00283 ,
this
00284 ,
false
00285 );
00286
00287 logger.
info(
"Group " +
groupName +
" connected to "
00288 +
channel.getLocalAddress());
00289
00290
00291
controllersMap.put(
channel.getLocalAddress(), controller.
getJmxName());
00292
00293
00294
currentView =
channel.getView();
00295
if (
currentView.size() == 1)
00296 {
00297 logger.
info(
Translate.get(
00298
"virtualdatabase.distributed.configuration.first.in.group",
00299
groupName));
00300
allMemberButUs =
new Vector(1);
00301
return;
00302 }
00303
00304
00305
allMemberButUs = (Vector)
currentView.getMembers().clone();
00306
00307
00308
00309 ((
DistributedRequestManager) requestManager)
00310 .setControllerId(
allMemberButUs.indexOf(
channel.getLocalAddress()));
00311
allMemberButUs.remove(
channel.getLocalAddress());
00312
00313
00314
if (
checkConfigurationCompatibility(
allMemberButUs) ==
false)
00315 {
00316 String msg =
Translate
00317 .get(
"virtualdatabase.distributed.configuration.not.compatible");
00318 logger.
error(msg);
00319
throw new ControllerException(msg);
00320 }
00321
00322 logger.
info(
Translate
00323 .get(
"virtualdatabase.distributed.configuration.compatible"));
00324
00325
00326
00327
broadcastBackendInformation(
allMemberButUs);
00328 }
00329
catch (Exception e)
00330 {
00331 String msg =
Translate.get(
"virtualdatabase.distributed.joingroup.error",
00332
groupName);
00333
if (e instanceof RuntimeException)
00334 logger.
error(msg, e);
00335
throw new Exception(msg +
" (" + e +
")");
00336 }
00337 }
00338
00344 public JChannel
getChannel()
00345 {
00346
return channel;
00347 }
00348
00354 public MessageDispatcher
getDispatcher()
00355 {
00356
return dispatcher;
00357 }
00358
00364 public View
getCurrentView()
00365 {
00366
return currentView;
00367 }
00368
00374 public Vector
getAllMemberButUs()
00375 {
00376
return allMemberButUs;
00377 }
00378
00389 private boolean checkConfigurationCompatibility(Vector dest)
00390 {
00391
if (logger.
isDebugEnabled())
00392 logger.
debug(
Translate
00393 .get(
"virtualdatabase.distributed.configuration.checking"));
00394
00395
00396 RspList rspList =
dispatcher.castMessage(dest,
CJDBCGroupMessage
00397 .getMessage(
new VirtualDatabaseConfiguration(
this)),
00398 GroupRequest.GET_ALL,
CJDBCGroupMessage.defaultCastTimeOut);
00399
00400
00401 Vector results = rspList.getResults();
00402
int size = results.size();
00403
if (size == 0)
00404 logger.
warn(
Translate
00405 .get(
"virtualdatabase.distributed.configuration.checking.noanswer"));
00406
for (
int i = 0; i < size; i++)
00407 {
00408 Object response = results.get(i);
00409
if (response instanceof Boolean)
00410 {
00411
if (((Boolean) response).booleanValue() ==
false)
00412
return false;
00413 }
00414
else
00415 {
00416 logger
00417 .
error(
"Unexpected response while checking configuration compatibility: "
00418 + response);
00419
return false;
00420 }
00421 }
00422
00423
00424
return true;
00425 }
00426
00432 private void broadcastBackendInformation(Vector dest)
00433 {
00434 logger
00435 .
debug(
Translate
00436 .get(
"virtualdatabase.distributed.configuration.querying.remote.status"));
00437
00438
00439 RspList rspList =
dispatcher.castMessage(dest,
CJDBCGroupMessage
00440 .getMessage(
new BackendStatus(
getBackendsInfo(backends))),
00441 GroupRequest.GET_ALL,
CJDBCGroupMessage.defaultCastTimeOut);
00442
00443
int size = dest.size();
00444
for (
int i = 0; i < size; i++)
00445 {
00446
00447 Address addr = (Address) dest.get(i);
00448
if (rspList.isReceived(addr))
00449 {
00450
if (logger.
isDebugEnabled())
00451 logger
00452 .
debug(
Translate
00453 .get(
00454
"virtualdatabase.distributed.configuration.updating.backend.list",
00455 addr.toString()));
00456 }
00457
else
00458 logger.
warn(
Translate.get(
00459
"virtualdatabase.distributed.unable.get.remote.status", addr
00460 .toString()));
00461 }
00462 }
00463
00474 public boolean isCompatibleBackend(
BackendInfo backend)
00475
throws VirtualDatabaseException
00476 {
00477
try
00478 {
00479
acquireReadLockBackendLists();
00480 }
00481
catch (InterruptedException e)
00482 {
00483 String msg =
"Unable to acquire read lock on backend list in isCompatibleBackend ("
00484 + e +
")";
00485 logger.
error(msg);
00486
throw new VirtualDatabaseException(msg);
00487 }
00488
00489
try
00490 {
00491
00492 String backendURL = backend.getUrl();
00493
int size = backends.size();
00494
DatabaseBackend b = null;
00495
for (
int i = 0; i < size; i++)
00496 {
00497 b = (
DatabaseBackend) backends.get(i);
00498
if (b.
getURL().equals(backendURL))
00499
return false;
00500 }
00501 }
00502
catch (RuntimeException re)
00503 {
00504
throw new VirtualDatabaseException(re);
00505 }
00506 finally
00507 {
00508
releaseReadLockBackendLists();
00509 }
00510
00511
return true;
00512 }
00513
00514
00515
00516
00517
00521 public Object
handle(Message msg)
00522 {
00523
try
00524 {
00525
if (msg != null)
00526 {
00527 Object content = msg.getObject();
00528
if (content instanceof
DistributedRequest)
00529 {
00530
if (logger.
isDebugEnabled())
00531 logger.
debug(
getControllerName() +
": DistributedRequest "
00532 + ((
DistributedRequest) content).getRequest().getId()
00533 +
" from " +
controllersMap.get(msg.getSrc()));
00534
return ((Serializable) ((
DistributedRequest) content)
00535 .executeRequest((
DistributedRequestManager)
this.requestManager));
00536 }
00537
if (content instanceof
BackendTransfer)
00538 {
00539 logger.
info(
getControllerName()+
":Received transfer command");
00540
BackendTransfer transfer = (
BackendTransfer) content;
00541
BackendInfo info = transfer.
getInfo();
00542
DatabaseBackend backend =
new DatabaseBackend(info);
00543
try
00544 {
00545
this.addBackend(backend);
00546 }
00547
catch (Exception e1)
00548 {
00549 logger.
error(
"Transfer failed",e1);
00550
return e1;
00551 }
00552 logger.
info(
getControllerName()+
":Enable backend");
00553
enableBackend(backend.
getName());
00554
return Boolean.TRUE;
00555 }
00556
if (content instanceof
ControllerName)
00557 {
00558 String controllerName = ((
ControllerName) content).getJmxName();
00559
if (logger.
isDebugEnabled())
00560 logger.
debug(
getControllerName() +
": New ControllerName "
00561 + controllerName);
00562
controllersMap.put(msg.getSrc(), controllerName);
00563
return Boolean.TRUE;
00564 }
00565
if (content instanceof
Commit)
00566 {
00567
if (logger.
isDebugEnabled())
00568 logger.
debug(
getControllerName() +
": Commit from "
00569 +
controllersMap.get(msg.getSrc()));
00570
return ((Serializable) ((
Commit) content)
00571 .commit((
DistributedRequestManager)
this.requestManager));
00572 }
00573
if (content instanceof
Rollback)
00574 {
00575
if (logger.
isDebugEnabled())
00576 logger.
debug(
getControllerName() +
": Rollback from "
00577 +
controllersMap.get(msg.getSrc()));
00578
return ((Serializable) ((
Rollback) content)
00579 .rollback((
DistributedRequestManager)
this.requestManager));
00580 }
00581
else if (content instanceof
VirtualDatabaseConfiguration)
00582 {
00583
VirtualDatabaseConfiguration vdc = (
VirtualDatabaseConfiguration) content;
00584
00585
if (
MBeanServerManager.isJmxEnabled())
00586 {
00587 Hashtable data =
new Hashtable();
00588 data.put(
"controllerName", vdc.
getControllerName());
00589 data.put(
"rmiconnector",
new String[]{vdc.
getRmiHostname(),
00590 vdc.
getRmiPort()});
00591
RmiConnector.broadcastNotification(
this,
00592
CjdbcNotificationList.DISTRIBUTED_CONTROLLER_ADDED,
00593
CjdbcNotificationList.NOTIFICATION_LEVEL_INFO,
Translate
00594 .get(
"notification.distributed.controller.added", this
00595 .getName()), data);
00596 }
00597
controllersMap.put(msg.getSrc(), vdc.getControllerJmxName());
00598
if (logger.
isDebugEnabled())
00599 logger.
debug(
"VirtualDatabaseConfiguration from "
00600 + vdc.getControllerName());
00601
00602
00603 Vector target =
new Vector();
00604 target.add(msg.getSrc());
00605
dispatcher.castMessage(target,
CJDBCGroupMessage
00606 .getMessage(
new ControllerName(controller.
getName(), controller
00607 .
getJmxName())), GroupRequest.GET_ALL,
00608
CJDBCGroupMessage.defaultCastTimeOut);
00609
00610
00611
dispatcher.castMessage(target,
CJDBCGroupMessage
00612 .getMessage(
new BackendStatus(
getBackendsInfo(backends))),
00613 GroupRequest.GET_ALL,
CJDBCGroupMessage.defaultCastTimeOut);
00614
00615
if (
isLocalMessage(msg))
00616
return Boolean.TRUE;
00617
else
00618
return new Boolean((vdc.isCompatible(
this)));
00619 }
00620
else if (content instanceof
BackendStatus)
00621 {
00622 Address src = msg.getSrc();
00623 ArrayList remoteBackendList = ((
BackendStatus) content).getBackends();
00624
backendsPerController.put(src, remoteBackendList);
00625
if (logger.
isInfoEnabled())
00626 logger
00627 .
info(
Translate
00628 .get(
00629
"virtualdatabase.distributed.configuration.updating.backend.list",
00630
controllersMap.get(src)));
00631 }
00632
else if (content instanceof
EnableBackend)
00633 {
00634 Address src = msg.getSrc();
00635 ArrayList remoteBackendList = (ArrayList)
backendsPerController
00636 .get(src);
00637
DatabaseBackend enabledBackend = ((
EnableBackend) content)
00638 .getBackend();
00639
int size = remoteBackendList.size();
00640
boolean backendFound =
false;
00641
for (
int i = 0; i < size; i++)
00642 {
00643
DatabaseBackend b = (
DatabaseBackend) remoteBackendList.get(i);
00644
if (b.
equals(enabledBackend))
00645 {
00646 logger.
info(
"Backend " + b.
getName() +
" enabled on controller "
00647 +
controllersMap.get(src));
00648 remoteBackendList.set(i, enabledBackend);
00649 backendFound =
true;
00650
break;
00651 }
00652 }
00653
if (!backendFound)
00654 {
00655 logger.
warn(
"Updating backend list with unknown backend "
00656 + enabledBackend.
getName() +
" enabled on controller "
00657 +
controllersMap.get(src));
00658 remoteBackendList.add(enabledBackend);
00659 }
00660 }
00661
else
00662 {
00663 logger.
warn(
"Unhandled message type received: " + content.getClass()
00664 +
"(" + content +
")");
00665 }
00666 }
00667
else
00668 {
00669 String errorMsg =
"Invalid null message";
00670 logger.
error(errorMsg);
00671
return new ControllerException(errorMsg);
00672 }
00673
return msg.makeReply();
00674 }
00675
catch (Exception e)
00676 {
00677
if (e instanceof RuntimeException)
00678 logger.
warn(
"Error while handling group message:"
00679 + msg.getObject().getClass(), e);
00680
return e;
00681 }
00682 }
00683
00684 private boolean isLocalMessage(Message msg)
00685 {
00686
return channel.getLocalAddress().equals(msg.getSrc());
00687 }
00688
00692 public void getBackendStatus()
00693 {
00694
if (logger.isDebugEnabled())
00695 logger.debug(
"Requesting remote controllers status");
00696 RspList rspList = dispatcher.castMessage(null,
CJDBCGroupMessage
00697 .getMessage(
new BackendStatus(getBackendsInfo(backends))),
00698 GroupRequest.GET_ALL,
CJDBCGroupMessage.defaultCastTimeOut);
00699 Vector results = rspList.getResults();
00700
int size = results.size();
00701
for (
int i = 0; i < size; i++)
00702 {
00703 ArrayList b = (ArrayList) results.get(i);
00704
int bSize = b.size();
00705
if (bSize == 0)
00706 logger.debug(
"No Database Backends");
00707
else
00708
for (
int j = 0; j < bSize; j++)
00709 logger.debug(((
DatabaseBackend) b.get(j)).getXml());
00710 }
00711 }
00712
00713
00714
00715
00716
00720 public void receive(Message msg)
00721 {
00722
if (logger.isDebugEnabled())
00723 logger.debug(
"Received message: " + msg +
" (header:"
00724 + msg.printObjectHeaders() +
")");
00725 }
00726
00730 public byte[] getState()
00731 {
00732
return null;
00733 }
00734
00738 public void setState(byte[] state)
00739 {
00740 }
00741
00742
00743
00744
00745
00749 public void block()
00750 {
00751
if (logger.isDebugEnabled())
00752 logger.debug(
"Messages should be freezed until new view is installed.");
00753 }
00754
00758 public void suspect(Address suspectedMember)
00759 {
00760 logger.warn(
"Member " + suspectedMember +
" is suspected of failure");
00761 }
00762
00766 public void viewAccepted(View newView)
00767 {
00768 Vector newMembers = newView.getMembers();
00769
int newSize = newMembers.size();
00770
for (
int i = 0; i < newSize; i++)
00771 {
00772 Address addr = (Address) newMembers.get(i);
00773
if (!currentView.containsMember(addr))
00774 {
00775 logger.info(controller.getName() +
":New controller " + addr.toString()
00776 +
" detected.");
00777 }
00778 }
00779 Vector currentMembers = currentView.getMembers();
00780 logger.info(controller.getName() +
":Current Members:" + currentMembers);
00781
int currentSize = currentMembers.size();
00782
for (
int i = 0; i < currentSize; i++)
00783 {
00784 Address addr = (Address) currentMembers.get(i);
00785
if (!newView.containsMember(addr))
00786 {
00787 logger.warn(
"Controller " + addr +
" has failed.");
00788 }
00789 }
00790 currentView = newView;
00791 currentMembers = currentView.getMembers();
00792 logger.info(controller.getName() +
":new Members:" + currentMembers);
00793 allMemberButUs = ((Vector) currentView.getMembers().clone());
00794 allMemberButUs.remove(channel.getLocalAddress());
00795 }
00796
00797
00798
00799
00800
00806 public HashMap getBackendRecoveryPolicy()
00807 {
00808
return backendRecoveryPolicy;
00809 }
00810
00816 public boolean isDistributed()
00817 {
00818
return true;
00819 }
00820
00828 public boolean equals(Object other)
00829 {
00830
if ((other == null)
00831 || (!(other instanceof org.objectweb.cjdbc.controller.virtualdatabase.DistributedVirtualDatabase)))
00832
return false;
00833
else
00834 {
00835
DistributedVirtualDatabase db = (org.objectweb.cjdbc.controller.virtualdatabase.DistributedVirtualDatabase) other;
00836
return name.equals(db.
getDatabaseName())
00837 && groupName.equals(db.
getGroupName());
00838 }
00839 }
00840
00846 protected String getDistributionXml()
00847 {
00848 StringBuffer info =
new StringBuffer();
00849 info.append(
"<" +
DatabasesXmlTags.ELT_Distribution +
" "
00850 +
DatabasesXmlTags.ATT_groupName +
"=\"" + groupName +
"\">");
00851
00852
for (Iterator iter = backendRecoveryPolicy.values().iterator(); iter
00853 .hasNext();)
00854 {
00855
BackendRecoveryPolicy p = (
BackendRecoveryPolicy) iter.next();
00856 info.append(p.
getXml());
00857 }
00858
00859 info.append(
"</" +
DatabasesXmlTags.ELT_Distribution +
">");
00860
return info.toString();
00861 }
00862
00866 public String[] viewControllerList()
00867 {
00868
if (logger.isInfoEnabled())
00869 {
00870 logger.info(channel.getLocalAddress() +
" see members:"
00871 + currentView.getMembers() +
" and has mapping:" + controllersMap);
00872 }
00873 String[] members =
new String[controllersMap.keySet().size()];
00874 Iterator iter = controllersMap.keySet().iterator();
00875
int i = 0;
00876
while (iter.hasNext())
00877 {
00878 members[i] = (String) controllersMap.get(iter.next());
00879 i++;
00880 }
00881
return members;
00882 }
00883
00889 public void setAuthenticationManager(
00890
AuthenticationManager authenticationManager)
00891 {
00892 super.setAuthenticationManager(authenticationManager);
00893 }
00894
00898 public Hashtable viewGroupBackends() throws
VirtualDatabaseException
00899 {
00900 Hashtable map =
new Hashtable(controllersMap.size());
00901 Iterator iter = backendsPerController.keySet().iterator();
00902 Address addr;
00903
while (iter.hasNext())
00904 {
00905 addr = (Address) iter.next();
00906 map.put(controllersMap.get(addr), backendsPerController.get(addr));
00907 }
00908
return map;
00909 }
00910
00922 public ArrayList getBackendsInfo(ArrayList backendsObject)
00923 {
00924
int size = backendsObject.size();
00925 ArrayList infos =
new ArrayList(size);
00926
DatabaseBackend backend;
00927
for (
int i = 0; i < size; i++)
00928 {
00929 backend = (
DatabaseBackend) backendsObject.get(i);
00930 infos.add(createBackendInfo(backend,
false));
00931 }
00932
return infos;
00933 }
00934
00943 public BackendInfo createBackendInfo(
DatabaseBackend backend,
boolean useXml)
00944 {
00945
if (useXml)
00946
try
00947 {
00948
return new BackendInfo(backend.
getXml());
00949 }
00950
catch (DocumentException e)
00951 {
00952
00953 }
00954
return new BackendInfo(backend.
getName(), backend.
getDriverPath(), backend
00955 .
getDriverClassName(), backend.
getURL(), backend
00956 .
getConnectionTestStatement());
00957 }
00958
00962 public void removeBackend(String backend)
throws VirtualDatabaseException
00963 {
00964 super.removeBackend(backend);
00965
00966
00967 broadcastBackendInformation(allMemberButUs);
00968 }
00969
00973 public void transferBackend(String backend, String controllerDestination)
00974
throws VirtualDatabaseException
00975 {
00976
00977 Vector dest =
new Vector(1);
00978 Iterator iter = controllersMap.entrySet().iterator();
00979 Entry entry;
00980 Address targetAddr = null;
00981
while (iter.hasNext())
00982 {
00983 entry = (Entry) iter.next();
00984
if (entry.getValue().equals(controllerDestination))
00985 targetAddr = (Address) entry.getKey();
00986 }
00987
if (targetAddr == null)
00988
throw new VirtualDatabaseException(
"Cannot find controller:"
00989 + controllerDestination +
" in group");
00990 dest.add(targetAddr);
00991
00992
00993
DatabaseBackend db = getAndCheckBackend(backend, NO_CHECK_BACKEND);
00994
00995
00996
try
00997 {
00998
DistributedRequestManager manager =((
DistributedRequestManager) requestManager) ;
00999
if(hasRecoveryLog())
01000 manager.
disableBackendForCheckpoint(db,
"transfer of " + backend +
" to :" + controllerDestination);
01001
else
01002 manager.
disableBackend(db);
01003 }
01004
catch (SQLException e)
01005 {
01006
throw new VirtualDatabaseException(e.getMessage());
01007 }
01008
01009
01010 logger.info(
"Sending transfer message to:"+targetAddr);
01011 dispatcher.castMessage(dest,
CJDBCGroupMessage
01012 .getMessage(
new BackendTransfer(controllerDestination,createBackendInfo(db,
true))),
01013 GroupRequest.GET_ALL,
CJDBCGroupMessage.defaultCastTimeOut);
01014
01015
01016 removeBackend(db);
01017
01018
01019 broadcastBackendInformation(allMemberButUs);
01020 }
01021 }