Package com.sun.jini.test.share

Source Code of com.sun.jini.test.share.KillVMUtil$KillVMObjectImpl$KillVMThread

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.sun.jini.test.share;

//import com.sun.jini.start.ClassLoaderUtil;

import java.io.IOException;

import java.net.MalformedURLException;

import java.rmi.activation.Activatable;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationException;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;

import java.rmi.MarshalledObject;
import java.rmi.Remote;

import java.rmi.RemoteException;

/**
* This class contains a set of static classes and methods that provide
* general-purpose functions related to shutting down an ActivationGroup (VM)
* in which one or activatable processes are executing. This utility class
* is intended to be useful to all categories of tests that wish to simulate
* a system crash. For example, tests that verify the ability of an
* application to persist its state may find this utility particularly
* useful.
*/
public class KillVMUtil {
    /** Utility method used to kill the VM (ActivationGroup) referenced
     *  by the <code>gid</code> parameter. If an activatable service is
     *  started in NON-restartable mode, calling this method with
     *  the <code>ActivationGroupID</code> of that service's
     *  <code>ActivationGroup</code> will cause a special object to be
     *  registered with that VM; an object whose only function is to
     *  perform a <code>System.exit</code> on the VM. After registering
     *  this special object with the indicated <code>ActivationGroup</code>,
     *  this method invokes the killVM() method on that object, resulting
     *  in the stoppage of all processes running in the VM.
     *
     *  Note that if the original service was started in restart mode,
     *  after stopping the VM, RMID will simply re-spawn the VM and
     *  re-start the service.
     */
    public static void killActivationGroup(ActivationGroupID gid)
                                   throws MalformedURLException,
                                          ActivationException, RemoteException
    {
        String implClass = KillVMObjectImpl.class.getName();
  String codeLocation = null; //BDJ - TEMP WORKAROUND FOR COMPILE
//          String codeLocation = ClassLoaderUtil.URLsToString
//                                (ClassLoaderUtil.getClasspathURLs
//                                 (System.getProperty("java.class.path")));
        ActivationDesc desc = new ActivationDesc(gid,implClass,
                                                 codeLocation,null,false);
        KillVMObject serverStub = (KillVMObject)(Activatable.register(desc));
        long delay = serverStub.killVM();       
        try {Thread.sleep(delay);} catch (InterruptedException e) { }
    }//end killActivationGroup

    /** Remote interface that should be implemented by any object desiring
     *  the capability to abruptly stop all processes in a given
     *  ActivationGroup (VM).
     */
    public interface KillVMObject extends Remote {
        /** Abruptly stops the VM in which this method's implementation
         *  executes.
         * 
         * @return a <code>long</code> value representing an estimate of the
         *         number of milliseconds that will elapse before the VM is
         *         completely shutdown. The caller of this method should not
         *         call any processes in this VM until after this time has
         *         elapsed.
         */
        public long killVM() throws java.rmi.RemoteException;
    }//end interface KillVMObject

    /** Special activatable class whose instance, once registered with a
     *  given ActivationGroup (VM), can be used to completely stop (or "kill")
     *  all processes registered and running in that VM.
     *
     *  Note that because calls to this class' killVM() method are
     *  asynchronous, certain requirements are imposed on the implementation.
     *  If the VM is exited from the current thread, rather than from a
     *  separate thread, entities which invoke this method will always
     *  receive a <code>RemoteException</code> because exiting the VM in
     *  the current thread will break the communication link between the
     *  frontend and the backend of the service. Thus, the VM must be
     *  exited from a separate thread.
     * 
     *  Another implementation requirement, related to the thread requirement,
     *  involves preventing <code>RemoteException</code>s through the
     *  introduction of timing delays. If the VM is exited before the remote
     *  call has had a chance to complete, just as with the case of exiting
     *  the VM from the current thread, the communication link between the
     *  this class' frontend and backend will be broken, resulting in a
     *  <code>RemoteException</code>. Thus, not only must the VM be exited
     *  from a separate thread, but it also must be exited only after the
     *  remote call to this method has completed. By instructing the thread
     *  that exits the VM to delay a certain amount of time before actually
     *  exiting the VM, this method attempts to "guarantee" that the VM will
     *  not be exited until the remote call has completed. Note that the
     *  amount of time to delay is simply a rough estimate of the amount
     *  of time a typical remote call should take to complete. Thus, a
     *  <code>RemoteException</code> may occur because the time delay is
     *  too small.
     *
     *  Next, note that the use of the killVM() method also imposes a related
     *  timing requirement on the client-side entity. That is, when an
     *  entity invokes this method, it must also delay a certain amount
     *  time before attempting to again interact with any process that
     *  was registered with the killed VM in restart mode. This delay is
     *  necessary to allow such services to be re-activated and to recover
     *  any persisted state. The killVM() method returns a <code>long</code>
     *  value that represents the amount of time the client-side entity
     *  should delay before again attempting to interact with those
     *  restartable processes. As with the server side time estimate,
     *  this time value is a rough estimate, and may need to be adjusted
     *  if the entity experiences <code>RemoteException</code>s on a
     *  regular basis when the entity attempts to interact with any
     *  restarted processes after invoking this method.
     *
     *  Finally, note that because this class is an inner class, it must
     *  be declared static. If it is not declared static, misleading
     *  ActivationExceptions will occur that seem to indicate a missing
     *  activation constructor (the exception will also say something about
     *  and problems while intializing (<init>). These exceptions occur
     *  because the non-static inner class will have an implicit reference
     *  to the outter class which is not registered with the activation
     *  system.
     */
    public static class KillVMObjectImpl implements KillVMObject {
        public KillVMObjectImpl(ActivationID activationID,
                                MarshalledObject data) throws IOException
        {
            Activatable.exportObject(this, activationID, 0);
        }//end constructor
        public long killVM() throws RemoteException {
            long delay = 20; // wait N milliseconds before exiting VM
            (new KillVMThread(delay)).start();
            return (delay*1000); //just an estimate
        }
        private class KillVMThread extends Thread {
            long delay;
      /** Thread that inherits its daemon status from main thread */
      public KillVMThread(long delay) {
          super("killVM");
                this.delay = delay;
            }
      public void run() {
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) { }
                System.exit(0);
      }
        }//end class KillVMThread
    }//end class KillVMObjectImpl

} //end class KillVMUtil

TOP

Related Classes of com.sun.jini.test.share.KillVMUtil$KillVMObjectImpl$KillVMThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.