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 }
|