src/org/objectweb/cjdbc/controller/virtualdatabase/DistributedVirtualDatabase.java

説明を見る。
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 // How the code is organized ? 00092 // 00093 // 1. Member variables 00094 // 2. Constructor(s) 00095 // 3. Request handling 00096 // 4. Transaction handling 00097 // 5. Database backend management 00098 // 6. Distribution management (multicast) 00099 // 7. Getter/Setter (possibly in alphabetical order) 00100 // 00101 00102 // Distribution 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 // Constructors 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 // Add the backend to the virtual database. 00175 super.addBackend(db); 00176 00177 // Send a group message if already joined group 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 // Distribution handling 00249 // 00250 00257 public void joinGroup() throws Exception 00258 { 00259 try 00260 { 00261 // Read the protocol stack configuration from jgroups.xml 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 // Join the group 00276 channel.connect(groupName); 00277 dispatcher = new MessageDispatcher(channel /* 00278 * group 00279 * channel 00280 */ 00281 , this /* messageListener */ 00282 , this /* membershipListener */ 00283 , this /* requestHandler */ 00284 , false /* deadlock detection */ 00285 ); 00286 00287 logger.info("Group " + groupName + " connected to " 00288 + channel.getLocalAddress()); 00289 00290 // Add ourselves to the list of controllers 00291 controllersMap.put(channel.getLocalAddress(), controller.getJmxName()); 00292 00293 // Check if we are alone or not 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 // Compute the group list without us 00305 allMemberButUs = (Vector) currentView.getMembers().clone(); 00306 00307 // Our controller id is our position in the membership. 00308 // This assumes that all controllers have the view in the same order. 00309 ((DistributedRequestManager) requestManager) 00310 .setControllerId(allMemberButUs.indexOf(channel.getLocalAddress())); 00311 allMemberButUs.remove(channel.getLocalAddress()); 00312 00313 // Check with the other controller that our config is compatible 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 // Distribute backends among controllers knowing that at this point 00326 // there is no conflict on the backend distribution policies. 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 // Send our configuration 00396 RspList rspList = dispatcher.castMessage(dest, CJDBCGroupMessage 00397 .getMessage(new VirtualDatabaseConfiguration(this)), 00398 GroupRequest.GET_ALL, CJDBCGroupMessage.defaultCastTimeOut); 00399 00400 // Check that everybody agreed 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 // Ok, everybody replied true (config is compatible) 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 // Send our backend status 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 // Add the backend configuration of every remote controller 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 // Find the backend 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 // This backend does not exist here 00511 return true; 00512 } 00513 00514 // 00515 // Message dispatcher request handling 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 { //Distributed request execution 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 { //Distributed commit execution 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 { //Distributed commit execution 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 { // Check if given configuration is compatible with the local one 00583 VirtualDatabaseConfiguration vdc = (VirtualDatabaseConfiguration) content; 00584 // Send notification 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 // Send controller name to new comer 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 // Broadcast backends 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 { // Update backend list from sender 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 // Message listener interface 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 // Membership support 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 // Getter/Setter and tools (equals, ...) 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 // go to next method. cause we haven't returned yet 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 // Send a group message to update backend list 00967 broadcastBackendInformation(allMemberButUs); 00968 } 00969 00973 public void transferBackend(String backend, String controllerDestination) 00974 throws VirtualDatabaseException 00975 { 00976 // Get the target controller 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 // Get reference on backend 00993 DatabaseBackend db = getAndCheckBackend(backend, NO_CHECK_BACKEND); 00994 00995 // Disable backend 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 // Send backend transfer message 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 // Remove backend from this controller 01016 removeBackend(db); 01017 01018 // Broadcast updated backend list 01019 broadcastBackendInformation(allMemberButUs); 01020 } 01021 }

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