org/objectweb/proactive/core/runtime/jini/JiniRuntimeImpl.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.core.runtime.jini;
00032 
00033 import java.io.IOException;
00034 import java.rmi.AlreadyBoundException;
00035 import java.rmi.RemoteException;
00036 import java.security.SecureRandom;
00037 import java.util.Hashtable;
00038 import java.util.Vector;
00039 
00040 import org.objectweb.proactive.core.ProActiveException;
00041 import org.objectweb.proactive.core.node.NodeException;
00042 import org.objectweb.proactive.core.process.ExternalProcess;
00043 import org.objectweb.proactive.core.runtime.ProActiveRuntime;
00044 import org.objectweb.proactive.core.runtime.ProActiveRuntimeImpl;
00045 import org.objectweb.proactive.core.runtime.rmi.RmiProActiveRuntime;
00046 import org.objectweb.proactive.core.runtime.rmi.RmiProActiveRuntimeImpl;
00047 import org.objectweb.proactive.core.util.UrlBuilder;
00048 import org.objectweb.proactive.ext.security.ProActiveSecurityManager;
00049 
00050 import net.jini.core.entry.Entry;
00051 import net.jini.core.lease.Lease;
00052 import net.jini.core.lookup.ServiceID;
00053 import net.jini.core.lookup.ServiceItem;
00054 import net.jini.core.lookup.ServiceRegistrar;
00055 import net.jini.core.lookup.ServiceRegistration;
00056 import net.jini.discovery.DiscoveryEvent;
00057 import net.jini.lease.LeaseRenewalEvent;
00058 import net.jini.lookup.entry.Name;
00059 
00060 
00067 public class JiniRuntimeImpl extends RmiProActiveRuntimeImpl
00068     implements java.io.Serializable, net.jini.discovery.DiscoveryListener,
00069         net.jini.lease.LeaseListener, RmiProActiveRuntime {
00070     //    protected transient ProActiveRuntimeImpl proActiveRuntime;
00071     //    protected String proActiveRuntimeURL;
00072     //ServiceRegistar table used afterwards to register node service
00073     //Vector is used because the size is unknown and this class is synchronized
00074     protected java.util.Vector<ServiceRegistrar> registrarsTable;
00075 
00076     //table used to store references on runtime registration in order to be 
00077     //able to unregister it from all lookup services. There is no need for a Hashtable 
00078     //since there is only one key, but it is for coding purpose.
00079     protected java.util.Hashtable<String, Vector<ServiceRegistration>> jiniRuntimeMap;
00080 
00081     //table used to handle node's registration when discovery event is received after the node's creation
00082     protected java.util.Hashtable<String, Vector<ServiceRegistration>> jiniNodeMap;
00083 
00084     //table used to handle virtualnode's registration when discovery event is received after the virtualnode's registration
00085     //this table contains a mapping virtualNode's name and an arrayList that contains all associated ServiceRegistrations
00086     protected java.util.Hashtable<String, Vector<ServiceRegistration>> jiniVirtualNodeMap;
00087     private volatile boolean isRuntimeRegistered = false;
00088 
00089     // this object is not serializable
00090     protected transient net.jini.lease.LeaseRenewalManager leaseManager = new net.jini.lease.LeaseRenewalManager();
00091 
00092     //
00093     // -- Constructors -----------------------------------------------
00094     //
00095     public JiniRuntimeImpl() throws java.rmi.RemoteException {
00096         super(true);
00097         this.proActiveRuntime = ProActiveRuntimeImpl.getProActiveRuntime();
00098         this.proActiveRuntimeURL = buildRuntimeURL();
00099         this.jiniRuntimeMap = new java.util.Hashtable<String, Vector<ServiceRegistration>>();
00100         jiniRuntimeMap.put(proActiveRuntimeURL, new java.util.Vector<ServiceRegistration>());
00101         this.jiniNodeMap = new java.util.Hashtable<String, Vector<ServiceRegistration>>();
00102         this.jiniVirtualNodeMap = new java.util.Hashtable<String, Vector<ServiceRegistration>>();
00103         this.registrarsTable = new java.util.Vector<ServiceRegistrar>();
00104         net.jini.discovery.LookupDiscovery discover = null;
00105         try {
00106             discover = new net.jini.discovery.LookupDiscovery(net.jini.discovery.LookupDiscovery.ALL_GROUPS);
00107             // stay around long enough to receice replies
00108             //Thread.currentThread().sleep(10000L);
00109         } catch (Exception e) {
00110             runtimeLogger.error(e.toString());
00111         }
00112 
00113         discover.addDiscoveryListener(this);
00114     }
00115 
00116     //
00117     // -- PUBLIC METHODS -----------------------------------------------
00118     //
00119     //
00120     // -- Implements JiniRuntime -----------------------------------------------
00121     //
00122     public ExternalProcess getProcessToDeploy(
00123         ProActiveRuntime proActiveRuntimeDist, String creatorID, String vmName,
00124         String padURL) throws ProActiveException, IOException {
00125         return proActiveRuntime.getProcessToDeploy(proActiveRuntimeDist,
00126             creatorID, vmName, padURL);
00127     }
00128 
00129     public String createLocalNode(String nodeName,
00130         boolean replacePreviousBinding,
00131         ProActiveSecurityManager securityManager, String vnname, String jobId)
00132         throws RemoteException, NodeException, AlreadyBoundException {
00133         //counter used to check that the node has been registered at 
00134         //least once as jini service
00135         //int counter = 0;
00136         //wait until the discovered method is called
00137         //otherwise registars could be null, because it is 
00138         //another thread that fulfill this table
00139         while (!isRuntimeRegistered) {
00140         }
00141         String nodeURL = null;
00142 
00143         //first we build a well-formed url
00144         try {
00145             nodeURL = buildNodeURL(nodeName);
00146             //then take the name of the node
00147             String name = UrlBuilder.getNameFromUrl(nodeURL);
00148 
00149             //System.out.println("name is : "+ name);
00150             //System.out.println("url is : "+ nodeURL);
00151             //create the node with the name 
00152             proActiveRuntime.createLocalNode(name, replacePreviousBinding,
00153                 securityManager, vnname, jobId);
00154         } catch (java.net.UnknownHostException e) {
00155             throw new java.rmi.RemoteException("Host unknown in " + nodeURL, e);
00156         }
00157 
00158         jiniNodeMap.put(nodeURL, registerService(nodeURL));
00159 
00160         return nodeURL;
00161     }
00162 
00163     public void killAllNodes() throws RemoteException, ProActiveException {
00164         for (java.util.Enumeration<String> e = jiniNodeMap.keys(); e.hasMoreElements();) {
00165             String nodeURL = e.nextElement();
00166             killNode(nodeURL);
00167         }
00168         proActiveRuntime.killAllNodes();
00169     }
00170 
00171     public void killNode(String nodeName)
00172         throws RemoteException, ProActiveException {
00173         String nodeUrl = null;
00174         String name = null;
00175         try {
00176             nodeUrl = buildNodeURL(nodeName);
00177             name = UrlBuilder.getNameFromUrl(nodeUrl);
00178             unregisterService(nodeUrl, jiniNodeMap);
00179         } catch (java.net.UnknownHostException e) {
00180             throw new java.rmi.RemoteException("Host unknown in " + nodeUrl, e);
00181         }
00182         proActiveRuntime.killNode(name);
00183     }
00184 
00185     public void killRT(boolean softly) throws Exception {
00186         killAllNodes();
00187         unregisterAllVirtualNodes();
00188         unregisterService(proActiveRuntimeURL, jiniRuntimeMap);
00189         proActiveRuntime.killRT(false);
00190     }
00191 
00192     public String getURL() {
00193         return proActiveRuntimeURL;
00194     }
00195 
00196     public void registerVirtualNode(String virtualNodeName,
00197         boolean replacePreviousBinding) throws RemoteException {
00198         String virtualNodeURL = null;
00199 
00200         //first we build a well-formed url
00201         try {
00202             virtualNodeURL = buildNodeURL(virtualNodeName);
00203         } catch (java.net.UnknownHostException e) {
00204             throw new java.rmi.RemoteException("Host unknown in " +
00205                 virtualNodeURL, e);
00206         }
00207 
00208         if (replacePreviousBinding) {
00209             if (jiniVirtualNodeMap.get(virtualNodeURL) != null) {
00210                 jiniVirtualNodeMap.remove(virtualNodeURL);
00211             }
00212         }
00213         if (!replacePreviousBinding &&
00214                 (jiniVirtualNodeMap.get(virtualNodeURL) != null)) {
00215             throw new java.rmi.RemoteException("VirtualNode " + virtualNodeURL +
00216                 " already registered as Jini service");
00217         }
00218 
00219         jiniVirtualNodeMap.put(virtualNodeURL, registerService(virtualNodeURL));
00220     }
00221 
00222     public void unregisterVirtualNode(String virtualNodeName)
00223         throws RemoteException, ProActiveException {
00224         String virtualNodeURL = null;
00225         proActiveRuntime.unregisterVirtualNode(UrlBuilder.removeVnSuffix(
00226                 virtualNodeName));
00227         //first we build a well-formed url
00228         try {
00229             virtualNodeURL = buildNodeURL(virtualNodeName);
00230             unregisterService(virtualNodeURL, jiniVirtualNodeMap);
00231         } catch (java.net.UnknownHostException e) {
00232             throw new java.rmi.RemoteException("Host unknown in " +
00233                 virtualNodeURL, e);
00234         }
00235     }
00236 
00237     public void unregisterAllVirtualNodes()
00238         throws RemoteException, ProActiveException {
00239         for (java.util.Enumeration<String> e = jiniVirtualNodeMap.keys();
00240                 e.hasMoreElements();) {
00241             String vnNodeURL = e.nextElement();
00242             unregisterVirtualNode(vnNodeURL);
00243         }
00244     }
00245 
00246     //
00247     // -- Implements  DiscoveryListener,LeaseListener-----------------------------------------------
00248     //
00249     public void discovered(DiscoveryEvent evt) {
00250         ServiceRegistrar[] registrars = evt.getRegistrars();
00251 
00252         //System.out.println("NB registrar "+registrars.length);
00253         // on cherche un registrar pour pouvoir s'enregistrer
00254         for (int n = 0; n < registrars.length; n++) {
00255             ServiceRegistrar registrar = registrars[n];
00256 
00257             ServiceRegistration reg = null;
00258             try {
00259                 // construction du service
00260                 //ServiceItem item = new ServiceItem(null, this, new Entry[] { new Name(proActiveRuntimeURL)});
00261                 ServiceItem item = new ServiceItem(newServiceID(), this,
00262                         new Entry[] { new Name(proActiveRuntimeURL) });
00263                 reg = registrar.register(item, Lease.FOREVER);
00264             } catch (Exception e) {
00265                 //e.printStackTrace();
00266                 runtimeLogger.error("register exception " + e.toString());
00267                 continue;
00268             }
00269             jiniRuntimeMap.get(proActiveRuntimeURL).add(reg);
00270 
00271             //add the registrar in the table for future use(node registration)
00272             registrarsTable.add(registrar);
00273 
00274             registerServiceAfterDiscovery(jiniNodeMap, registrar);
00275             registerServiceAfterDiscovery(jiniVirtualNodeMap, registrar);
00276             // on lance le lease manager pour que l'objet puisse se reenregistrer
00277             leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
00278             isRuntimeRegistered = true;
00279         }
00280 
00281         //we put this line in order to avoid deadlock in createLocalNode
00282         //Hence if a problem occurs when registering the runtime, we can still try to register
00283         //it in the createLocalNode method and an exception will be thrown in this method 
00284         isRuntimeRegistered = true;
00285     }
00286 
00287     public void discarded(DiscoveryEvent evt) {
00288     }
00289 
00290     public void notify(LeaseRenewalEvent evt) {
00291         runtimeLogger.info("Lease expired " + evt.toString());
00292         runtimeLogger.info(evt.getException().getMessage());
00293     }
00294 
00295     //
00296     // -- PROTECTED METHODS -----------------------------------------------
00297     //
00298     protected ServiceID newServiceID() {
00299 
00301         SecureRandom secRand = new SecureRandom();
00302 
00304         byte[] secRandBuf16 = new byte[16];
00305 
00306         secRand.nextBytes(secRandBuf16);
00307         secRandBuf16[6] &= 0x0f;
00308         secRandBuf16[6] |= 0x40; /* version 4 */
00309         secRandBuf16[8] &= 0x3f;
00310         secRandBuf16[8] |= 0x80; /* IETF variant */
00311         secRandBuf16[10] |= 0x80; /* multicast bit */
00312         long mostSig = 0;
00313         for (int i = 0; i < 8; i++) {
00314             mostSig = (mostSig << 8) | (secRandBuf16[i] & 0xff);
00315         }
00316         long leastSig = 0;
00317         for (int i = 8; i < 16; i++) {
00318             leastSig = (leastSig << 8) | (secRandBuf16[i] & 0xff);
00319         }
00320         return new ServiceID(mostSig, leastSig);
00321     }
00322 
00323     //
00324     // ---PRIVATE METHODS--------------------------------------
00325     //
00326     //This method is very useful when the JiniRuntime receives event about a new Lookup service
00327     //that was discovered.In such case, the runtime registers all nodes and virtualnodes previously registered
00328     //as Jini service with the registrar given as parameter and the corresponding hashtable
00329     private void registerServiceAfterDiscovery(Hashtable<String, Vector<ServiceRegistration>> jiniObjectTable,
00330         ServiceRegistrar registrar) {
00331         ServiceRegistration reg = null;
00332         ServiceID serviceID = null;
00333         if (!jiniObjectTable.isEmpty()) {
00334             synchronized (jiniObjectTable) {
00335                 for (java.util.Enumeration<String> e = jiniObjectTable.keys();
00336                         e.hasMoreElements();) {
00337                     String objectURL = e.nextElement();
00338                     Vector serviceRegistrationTable = jiniObjectTable.get(objectURL);
00339                     if (!serviceRegistrationTable.isEmpty()) {
00340                         serviceID = ((ServiceRegistration) serviceRegistrationTable.get(0)).getServiceID();
00341                     } else {
00342                         serviceID = newServiceID();
00343                     }
00344                     ServiceItem item = new ServiceItem(serviceID, this,
00345                             new Entry[] { new Name(objectURL) });
00346                     try {
00347                         reg = registrar.register(item, Lease.FOREVER);
00348                     } catch (Exception ex) {
00349                         runtimeLogger.info("register exception " +
00350                             ex.toString());
00351                         continue;
00352                     }
00353                     runtimeLogger.info(" Service Registered " + objectURL);
00354 
00355                     // on lance le lease manager pour que l'objet puisse se reenregistrer
00356                     leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
00357                     jiniObjectTable.get(objectURL).add(reg);
00358                 }
00359             }
00360         }
00361     }
00362 
00363     private String buildRuntimeURL() {
00364         String host = UrlBuilder.getHostNameorIP(getVMInformation()
00365                                                      .getInetAddress());
00366         String name = getVMInformation().getName();
00367         return UrlBuilder.buildUrl(host, name, "jini:");
00368     }
00369 
00370     private String buildNodeURL(String url)
00371         throws java.net.UnknownHostException {
00372         int i = url.indexOf('/');
00373         if (i == -1) {
00374             //it is an url given by a descriptor
00375             String host = UrlBuilder.getHostNameorIP(getVMInformation()
00376                                                          .getInetAddress());
00377             return UrlBuilder.buildUrl(host, url, "jini:");
00378         } else {
00379             return UrlBuilder.checkUrl(url);
00380         }
00381     }
00382 
00383     private Vector<ServiceRegistration> registerService(String objectUrl)
00384         throws java.rmi.RemoteException {
00385         //counter used to check that the object has been registered at 
00386         //least once as jini service
00387         int counter = 0;
00388         ServiceID serviceID = newServiceID();
00389         Vector<ServiceRegistration> serviceRegistrationTable = new Vector<ServiceRegistration>();
00390 
00391         //register it as a jini service with the url
00392         for (int n = 0; n < registrarsTable.size(); n++) {
00393             ServiceRegistrar registrar = registrarsTable.get(n);
00394             ServiceRegistration reg = null;
00395             try {
00396                 ServiceItem item = new ServiceItem(serviceID, this,
00397                         new Entry[] { new Name(objectUrl) });
00398                 reg = registrar.register(item, Lease.FOREVER);
00399                 counter++;
00400             } catch (Exception e) {
00401                 runtimeLogger.info("register exception " + e.toString());
00402                 continue;
00403             }
00404 
00405             // if counter=0 no node or vn are registered as jini Service
00406             if (counter == 0) {
00407                 throw new java.rmi.RemoteException("register exception ");
00408             }
00409             runtimeLogger.info("Service registered " + objectUrl);
00410             //System.out.println("Registrar "+registrar.getLocator().getHost());
00411             // on lance le lease manager pour que l'objet puisse se reenregistrer
00412             leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
00413             serviceRegistrationTable.add(reg);
00414         }
00415         return serviceRegistrationTable;
00416     }
00417 
00418     private void unregisterService(String objectUrl, Hashtable<String, Vector<ServiceRegistration>> jiniObjectTable)
00419         throws java.rmi.RemoteException {
00420         if (!jiniObjectTable.isEmpty()) {
00421             synchronized (jiniObjectTable) {
00422                 try {
00423                     Vector serviceRegistrationTable = jiniObjectTable.get(objectUrl);
00424                     if (!serviceRegistrationTable.isEmpty()) {
00425                         for (int i = 0; i < serviceRegistrationTable.size();
00426                                 i++) {
00427                             ServiceRegistration reg = (ServiceRegistration) serviceRegistrationTable.get(i);
00428                             reg.getLease().cancel();
00429                         }
00430                         if (objectUrl.indexOf("PA_JVM") < 0) {
00431                             runtimeLogger.info("Lease cancelled for " +
00432                                 objectUrl);
00433                         }
00434                     }
00435                 } catch (net.jini.core.lease.UnknownLeaseException e) {
00436                     throw new java.rmi.RemoteException(
00437                         "Unable to get the Lease for virtualNode " + objectUrl,
00438                         e);
00439                 } finally {
00440                     jiniObjectTable.remove(objectUrl);
00441                 }
00442             }
00443         }
00444     }
00445 }

Generated on Mon Jan 22 15:16:09 2007 for ProActive by  doxygen 1.5.1