Source code for /engineering/autohit-2003/src/autohit/server/Kernel.javaOriginal file Kernel.java
   1 /**
   2  * AUTOHIT 2003
   3  * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
   4  * 
   5  * This program is free software; you can redistribute it and/or modify 
   6  * it under the terms of the GNU General Public License as published by 
   7  * the Free Software Foundation; either version 2 of the License, or (at
   8  * your option) any later version.
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12  * more details.
  13  * 
  14  * You should have received a copy of the GNU General Public License along
  15  * with this program; if not, write to the Free Software Foundation, Inc.,
  16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17  *
  18  * Additional license information can be found in the documentation.
  19  * @author Erich P Gatejen
  20  */
  21 package autohit.server;
  22 
  23 import java.util.Enumeration;
  24 import java.util.Hashtable;
  25 import java.util.Iterator;
  26 import java.util.List;
  27 import java.util.Set;
  28 import java.util.Vector;
  29 
  30 import autohit.common.AutohitErrorCodes;
  31 import autohit.common.AutohitLogInjectorWrapper;
  32 import autohit.vm.VM;
  33 import autohit.vm.VMProcess;
  34 import autohit.common.ProcessMonitor;
  35 
  36 /**
  37  * Process kernel.  This is a basic kernel.  It does not run
  38  * in a monitor process.  It does not route commands or events.
  39  *
  40  * @author Erich P. Gatejen
  41  * @version 1.0
  42  * <i>Version History</i>
  43  * <code>EPG - Initial - 17May03<br>
  44  * EPG - Support new VMProcess scheme - 25Jul03<br>
  45  * EPG - Switch PCB table to a Vector - 28Jul03
  46  * </code>
  47  * 
  48  */
  49 public class Kernel {
  50 
  51 	/**
  52 	 *  Root system context
  53 	 */
  54 	private SystemContext sc;
  55 
  56 	/**
  57 	 *  Process table.  Maps processes to Integer(pid).
  58 	 */
  59 	private Hashtable ptable;
  60 
  61 	/**
  62 	 *  Logger
  63 	 */
  64 	private AutohitLogInjectorWrapper logger;
  65 
  66 	/**
  67 	 *  Write monitor
  68 	 */
  69 	private ProcessMonitor wmonitor;
  70 
  71 	/**
  72 	 *  The next pid to get.  One instance per jvm.
  73 	 *  Leaving it public in care there needs to be some
  74 	 *  segmentation voodoo in the server.
  75 	 */
  76 	static public int nextpid = 1;
  77 
  78 	// Number of processes before we bother sweaping the process table
  79 	public final static int PROCESS_CLEAN_THRESHOLD = 10;
  80 
  81 	/**
  82 	 *  Default constructor
  83 	 */
  84 	public Kernel() {
  85 		sc = null;
  86 		wmonitor = new ProcessMonitor();
  87 	}
  88 
  89 	/**
  90 	 *  Initialize.  It might be a bad idea to call this more than once,
  91 	 * since it could ghost a number of processes.
  92 	 * @param c is an instance of SystemContext
  93 	 * @see autohit.server.SystemContext
  94 	 */
  95 	public void init(SystemContext c) {
  96 		sc = c;
  97 		ptable = new Hashtable();
  98 		logger = c.getRootLogger();
  99 		logger.debug("Kernel: Initialized.", AutohitErrorCodes.CODE_DEBUGGING);
 100 	}
 101 
 102 	/**
 103 	 *  Get a usable process.  Create it if neccesssary.  It will
 104 	 * instantiate a default VMProcess implementation.
 105 	 * @return a VMProcess or null if failed
 106 	 */
 107 	public VMProcess get() {
 108 		return this.get("autohit.vm.VMProcessAutomat");
 109 	}
 110 
 111 	/**
 112 	 *  Get a usable process.  Create it if neccesssary.
 113 	 * @param processImpl class name for process implementation
 114 	 * @return a VMProcess or null if failed
 115 	 */
 116 	public VMProcess get(String processImpl) {
 117 
 118 		VMProcess pcb;
 119 		VMProcess result = null;
 120 		Object key;
 121 
 122 		try {
 123 
 124 			// LOCK everything
 125 			wmonitor.waitlock();
 126 
 127 			// Scrub the PCB table
 128 			if (ptable.size() >= PROCESS_CLEAN_THRESHOLD) {
 129 				this.scrubTable();
 130 			} // end scrub table
 131 
 132 			// Create the new process
 133 			int newpid = this.nextPid();
 134 			Class t = Class.forName(processImpl);
 135 			pcb = (VMProcess) t.newInstance();
 136 
 137 			pcb.init(sc, newpid);
 138 			pcb.start();
 139 			ptable.put(new Integer(newpid), pcb);
 140 			result = pcb;
 141 
 142 			// Unlock it
 143 			wmonitor.unlock();
 144 
 145 			logger.info("Kernel: Process requested by get().  PID=" + newpid, AutohitErrorCodes.CODE_INFORMATIONAL_OK);
 146 
 147 		} catch (Exception epc) {
 148 			logger.info(
 149 				"Kernel: Fundimental problem trying to start a process.  The whole system may be degraded.  Message="
 150 					+ epc.getMessage(),
 151 				AutohitErrorCodes.CODE_CATASTROPHIC_FRAMEWORK_FAULT);
 152 		}
 153 		return result;
 154 	}
 155 
 156 	/**
 157 	 * Get an list of active processes.  This will take a snapshot of the
 158 	 * process list as a List of VMProcesses.
 159 	 * BEWARE!  Processes are very volatile.  Their state can 
 160 	 * change at any time.  It is quite possible that the VMProcess can go bad
 161 	 * after you get the list.  Also, be extra sure not to keep any references to a
 162 	 * VMProcess for very long.  The Kernel won't like this.
 163 	 * @return A List of VMProcesses (it may be empty)
 164 	 */
 165 	public List getProcessList() {
 166 
 167 		VMProcess pcb;
 168 
 169 		// LOCK everything
 170 		wmonitor.waitlock();
 171 
 172 		// Is there any list?
 173 		Vector theList = new Vector();
 174 		for (Enumeration e = ptable.elements(); e.hasMoreElements();) {
 175 			pcb = (VMProcess) e.nextElement();
 176 
 177 			// Add only active processes to the list
 178 			if ((pcb.getState() >= VM.STATE_ACTIVE_THRESHOLD)) {
 179 				theList.add(pcb);
 180 			}
 181 		}
 182 
 183 		wmonitor.unlock();
 184 
 185 		return theList;
 186 	}
 187 
 188 	/**
 189 	 * Get a process by pid.  it will return null if it isn't found.
 190 		 * @param pid the pid to get.
 191 	 * @return A VMProcess or null if not found.
 192 	 */
 193 	public VMProcess getProcess(int pid) {
 194 
 195 		VMProcess pcb = null;
 196 
 197 		// Get the process
 198 		Integer ipid = new Integer(pid);
 199 		if (ptable.containsKey(ipid)) {
 200 			pcb = (VMProcess) ptable.get(ipid);
 201 		}
 202 		return pcb;
 203 	}
 204 
 205 	/**
 206 	 * Force the PCB table to clean
 207 	 */
 208 	public void scrubTable() {
 209 
 210 		// LOCK everything
 211 		wmonitor.waitlock();
 212 
 213 		Integer ipid;
 214 		VMProcess pcb;
 215 		for (Enumeration e = ptable.keys(); e.hasMoreElements();) {
 216 			ipid = (Integer) e.nextElement();
 217 			pcb = (VMProcess) ptable.get(ipid);
 218 			if (pcb.getState() < VM.STATE_ACTIVE_THRESHOLD) {
 219 				logger.debug(
 220 					"Kernel:Defunct process removed from memory.  PID=" + ipid.toString(),
 221 					AutohitErrorCodes.CODE_INFORMATIONAL_OK);
 222 				pcb.kill();
 223 				ptable.remove(ipid);
 224 			} // end if
 225 
 226 		} //end for
 227 
 228 		wmonitor.unlock();
 229 	}
 230 
 231 	/**
 232 	 * finalizer
 233 	 * We will kill all the processors to make sure nothing ghosts.
 234 	 * Why?  It is possible that other objects will hold references
 235 	 * to the VMProcess, so will kill them here.
 236 	 */
 237 	protected void finalize() throws Throwable {
 238 		VMProcess pcb;
 239 		Object key;
 240 
 241 		super.finalize();
 242 
 243 		logger.info("Kernel: Exiting.  Killing managed processes.", AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 244 
 245 		Set setOfPcbs = ptable.keySet();
 246 		if (!setOfPcbs.isEmpty()) {
 247 			Iterator i = setOfPcbs.iterator();
 248 			while (i.hasNext()) {
 249 				key = i.next();
 250 				pcb = (VMProcess) ptable.get(key);
 251 				logger.debug("Kernel: Killing process.  PID=" + pcb.getPID(), AutohitErrorCodes.CODE_DEBUGGING);
 252 				pcb.kill();
 253 				ptable.remove(key);
 254 			}
 255 		}
 256 	}
 257 
 258 	/**
 259 	 * Next pid helper.
 260 	 */
 261 	private int nextPid() {
 262 		int candidate = nextpid;
 263 		nextpid++;
 264 		return candidate;
 265 	}
 266 
 267 }