User: mulder  
  Date: 00/09/29 10:00:08

  Modified:    src/main/org/jboss/dependencies DependencyManager.java
  Log:
  Shut down MBeans in an order consistant with their dependencies when the
  administrator hits Ctrl-C in the console.
  
  Revision  Changes    Path
  1.3       +109 -14   jboss/src/main/org/jboss/dependencies/DependencyManager.java
  
  Index: DependencyManager.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/dependencies/DependencyManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DependencyManager.java    2000/09/13 11:39:57     1.2
  +++ DependencyManager.java    2000/09/29 17:00:08     1.3
  @@ -13,6 +13,7 @@
   import java.util.Iterator;
   import java.util.Map;
   import java.util.Set;
  +import java.util.Vector;
   import javax.management.MBeanServer;
   import javax.management.ObjectName;
   import javax.management.ReflectionException;
  @@ -27,7 +28,7 @@
    * and then starts a list of MBeans according to the dependencies in the
    * file.
    * @author Aaron Mulder <[EMAIL PROTECTED]>
  - * @version $Revision: 1.2 $
  + * @version $Revision: 1.3 $
    */
   public class DependencyManager {
       // Static --------------------------------------------------------
  @@ -45,6 +46,7 @@
       private HashMap remainingBeans;
       private HashSet pendingBeans;
       private HashSet otherMBeans;
  +    private Vector mbeanStartOrder;
       private MBeanServer server;
   
       // Constructors --------------------------------------------------
  @@ -58,6 +60,7 @@
           remainingBeans = new HashMap();
           pendingBeans = new HashSet();
           otherMBeans = new HashSet();
  +        mbeanStartOrder = new Vector();
       }
   
       // Public --------------------------------------------------------
  @@ -89,6 +92,7 @@
           remainingBeans.clear();
           pendingBeans.clear();
           otherMBeans.clear();
  +        mbeanStartOrder.clear();
           Iterator it = server.queryNames(null, null).iterator();
   
           // Identify all the MBeans
  @@ -110,7 +114,7 @@
           it = ((Map)remainingBeans.clone()).keySet().iterator();
           while(it.hasNext()) {
               String next = (String)it.next();
  -            if(!processService(next)) {
  +            if(!processService(next, true)) {
                   System.out.println("Unable to start service '"+next+"'");
               }
           }
  @@ -124,11 +128,74 @@
               }
           }
   
  -        // Clear out remaining data structures.
  +        // Clear out remaining temporary data structures.
           System.out.println(loadedBeans.size()+" services and "+otherMBeans.size()+" 
other MBeans started.");
           loadedBeans.clear();
  -        dependencies.clear();
           otherMBeans.clear();
  +        mbeanStartOrder.clear();
  +    }
  +
  +    /**
  +     * Stops all the MBeans in a server in an order consistant with the
  +     * dependencies.
  +     */
  +    public void stopMBeans(MBeanServer server) {
  +        this.server = server;
  +        loadedBeans.clear();
  +        remainingBeans.clear();
  +        pendingBeans.clear();
  +        otherMBeans.clear();
  +        mbeanStartOrder.clear();
  +        Iterator it = server.queryNames(null, null).iterator();
  +
  +        // Identify all the MBeans
  +        while(it.hasNext()) {
  +            ObjectName name = (ObjectName)it.next();
  +            String service = getService(name);
  +            if(service == null) {
  +                otherMBeans.add(name);
  +                continue;
  +            }
  +            Set set = (Set)remainingBeans.get(service);
  +            if(set == null)
  +                set = new HashSet();
  +            set.add(name);
  +            remainingBeans.put(service, set);
  +        }
  +
  +        // Get ordering for all the MBeans that are services
  +        it = ((Map)remainingBeans.clone()).keySet().iterator();
  +        while(it.hasNext()) {
  +            String next = (String)it.next();
  +            if(!processService(next, false)) {
  +                System.out.println("Unable to stop service '"+next+"'");
  +            }
  +        }
  +
  +        // Stop all the MBeans that are not services
  +        it = otherMBeans.iterator();
  +        while(it.hasNext()) {
  +            ObjectName name = (ObjectName)it.next();
  +            if(!stopMBean(name)) {
  +                System.out.println("Unable to stop MBean 
'"+name.getCanonicalName()+"'");
  +            }
  +        }
  +
  +        // Stop all the MBeans that are services in the reverse of
  +        // the valid startup order.
  +        int max = mbeanStartOrder.size();
  +        for(int i=max-1; i >= 0; i--) {
  +            ObjectName name = (ObjectName)mbeanStartOrder.elementAt(i);
  +            if(!stopMBean(name)) {
  +                System.out.println("Unable to stop MBean 
'"+name.getCanonicalName()+"'");
  +            }
  +        }
  +
  +        // Clear out remaining temporary data structures.
  +        System.out.println(loadedBeans.size()+" services and "+otherMBeans.size()+" 
other MBeans stopped.");
  +        loadedBeans.clear();
  +        otherMBeans.clear();
  +        mbeanStartOrder.clear();
       }
   
       /**
  @@ -152,7 +219,7 @@
        * Loads all the dependencies for a service, and then the service itself.
        * This is a recursive process.
        */
  -    private boolean processService(String target) {
  +    private boolean processService(String target, boolean executeStart) {
           if(pendingBeans.contains(target))
               throw new RuntimeException("Circular dependencies!");
           if(loadedBeans.contains(target))
  @@ -161,19 +228,19 @@
           pendingBeans.add(target);
           Set set = (Set)dependencies.get(target);
           if(set == null) {
  -            return loadService(target);
  +            return loadService(target, executeStart);
           } else {
               Iterator it = set.iterator();
               while(it.hasNext()) {
                   Dependency dep = (Dependency)it.next();
                   if(DEBUG) System.out.println("  Service '"+target+"' depends on 
'"+dep.name+"'");
                   if(!loadedBeans.contains(dep.name)) {
  -                    boolean result = processService(dep.name);
  +                    boolean result = processService(dep.name, executeStart);
                       if(!result && dep.required)
                           return false;
                   }
               }
  -            return loadService(target);
  +            return loadService(target, executeStart);
           }
       }
   
  @@ -181,19 +248,25 @@
        * Loads all instances of a service.  That is, all MBeans which have
        * "service=target" in the ObjectName.
        */
  -    private boolean loadService(String target) {
  +    private boolean loadService(String target, boolean executeStart) {
           boolean loaded = false;
           Set set = (Set)remainingBeans.get(target);
           if(set != null) {
  -            if(DEBUG) System.out.println("Starting service '"+target+"'");
  +            if(DEBUG) System.out.println("Checking instances for service 
'"+target+"'");
               Iterator it = set.iterator();
               while(it.hasNext()) {
  -                loaded = startMBean((ObjectName)it.next());
  -                if(!loaded)
  -                    break;
  +                ObjectName oName = (ObjectName)it.next();
  +                mbeanStartOrder.add(oName);
  +                if(executeStart) {
  +                    loaded = startMBean(oName);
  +                    if(!loaded)
  +                        break;
  +                    loaded = true;
  +                } else {
  +                    loaded = true;
  +                }
               }
               remainingBeans.remove(target);
  -            dependencies.remove(target);
           }
           loadedBeans.add(target);
           pendingBeans.remove(target);
  @@ -220,6 +293,28 @@
               System.out.println("Error starting service 
'"+name.getCanonicalName()+"': "+t);
           }
           return loaded;
  +    }
  +
  +    /**
  +     * Calls the "destroy" method on an MBean.  If no such method is available,
  +     * that's OK, but if the call fails for another reason, returns false.
  +     */
  +    private boolean stopMBean(ObjectName name) {
  +        boolean stopped = false;
  +        if(DEBUG) System.out.println("Stopping instance 
'"+name.getCanonicalName()+"'");
  +        try {
  +            server.invoke(name, "destroy", new Object[0], new String[0]);
  +            stopped = true;
  +        } catch(ReflectionException e) {
  +            if(e.getTargetException() instanceof NoSuchMethodException) {
  +                stopped = true;  // This bean doesn't have a destroy!
  +            } else {
  +                System.out.println("Error stopping service 
'"+name.getCanonicalName()+"': "+e.getTargetException());
  +            }
  +        } catch(Throwable t) {
  +            System.out.println("Error stopping service 
'"+name.getCanonicalName()+"': "+t);
  +        }
  +        return stopped;
       }
   
       /**
  
  
  

Reply via email to