001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.tools.server.system;
027:
028: import java.io.Serializable;
029: import java.util.List;
030:
031: /**
032: * A status summary of a running process, which may or may
033: * not be a Java Virtual Machine, which includes references
034: * to parent/child processes and basic process information.
035: * <p>
036: * Some of this information is Operating System specific,
037: * such as the ability to track memory/cpu usage.
038: */
039: public final class ProcessStatus implements Serializable {
040:
041: /**
042: * Marking disabled or there is no relation with this
043: * ProcessStatus and the self-"marked" ProcessStatus.
044: *
045: * @see #getMark()
046: */
047: public static final int MARK_NONE = 0;
048:
049: /**
050: * This ProcessStatus is the single "marked" ProcessStatus.
051: *
052: * @see #getMark()
053: */
054: public static final int MARK_SELF = 1;
055:
056: /**
057: * This ProcessStatus contains the "marked" ProcessStatus as
058: * a child or (great+)grandchild.
059: *
060: * @see #getMark()
061: */
062: public static final int MARK_PARENT = 2;
063:
064: /**
065: * This ProcessStatus has the "marked" ProcessStatus as a
066: * parent or (great+)grandparent.
067: *
068: * @see #getMark()
069: */
070: public static final int MARK_CHILD = 3;
071:
072: /**
073: * @see #getMark()
074: */
075: public static final String[] MARK_STRINGS = new String[] { "none",
076: "self", "parent", "child", };
077:
078: //
079: // relation to other ProcessStatus entries
080: //
081:
082: private final ProcessStatus parent;
083: private final List children;
084: private int mark = MARK_NONE;
085:
086: //
087: // details
088: //
089:
090: private final long pid;
091: private final long ppid;
092: private final long start;
093: private final String user;
094: private final String cmd;
095:
096: //
097: // plenty can be added here... see "man ps"
098: //
099:
100: public ProcessStatus(ProcessStatus parent, List children, long pid,
101: long ppid, long start, String user, String cmd) {
102: this .parent = parent;
103: this .children = children;
104: this .pid = pid;
105: this .ppid = ppid;
106: this .start = start;
107: this .user = user;
108: this .cmd = cmd;
109: }
110:
111: //
112: // tree-relation to other ProcessStatus entries:
113: //
114:
115: /**
116: * Get the parent process's <code>ProcessStatus</code> of
117: * this process.
118: *
119: * Most <code>ProcessStatus</code> data structures will have
120: * a non-null <tt>getParent()</tt>. The important exceptions
121: * are:<ul>
122: * <li>the root
123: * <tt>(getParentProcessIdentifier() == 0)</tt>.</li>
124: * <li>a trimmed listing, where not all ProcessStatus
125: * entries are gathered.</li>
126: * </ul>
127: *
128: * @see #getParentProcessIdentifier()
129: */
130: public ProcessStatus getParent() {
131: return parent;
132: }
133:
134: /**
135: * Get an immutable list of children <code>ProcessStatus</code>
136: * processes.
137: */
138: public List getChildren() {
139: return children;
140: }
141:
142: //
143: // details:
144: //
145:
146: /**
147: * Get the process id.
148: */
149: public long getProcessIdentifier() {
150: return pid;
151: }
152:
153: /**
154: * Get the parent's process id.
155: *
156: * @see #getParent()
157: */
158: public long getParentProcessIdentifier() {
159: return ppid;
160: }
161:
162: /**
163: * Get the start time in milliseconds.
164: */
165: public long getStartTime() {
166: return start;
167: }
168:
169: /**
170: * Get the user name.
171: */
172: public String getUserName() {
173: return user;
174: }
175:
176: /**
177: * Get the command.
178: * <p>
179: * The result may contain whitespace and other control characters.
180: */
181: public String getCommand() {
182: return cmd;
183: }
184:
185: //
186: // mark utilities:
187: //
188:
189: /**
190: * Get the "mark" of this process in relation to the process
191: * that has the "MARK_SELF" tag.
192: * <p>
193: * This is a utility method for recursively tagging the
194: * process tree. For example, the result of a
195: * <code>ProcessStatusReader</code> could mark the JVM as the
196: * "MARK_SELF", it's parent processes as "MARK_PARENT", and
197: * all child processes as "MARK_CHILD". This facilitates
198: * the later display of this information.
199: *
200: * @see #mark()
201: */
202: public int getMark() {
203: return mark;
204: }
205:
206: /**
207: * Get the mark as a readable String.
208: *
209: * @see #getMark()
210: */
211: public String getMarkAsString() {
212: return MARK_STRINGS[mark];
213: }
214:
215: /**
216: * Mark this ProcessStatus as "MARK_NONE".
217: * <p>
218: * This is useful when preparing to call <tt>mark()</tt>. Note
219: * that for a clean "mark()" all ProcessStatus data structures
220: * must be first "unmark()"ed.
221: */
222: public void unmark() {
223: this .mark = MARK_NONE;
224: }
225:
226: /**
227: * Mark this ProcessStatus with "MARK_SELF",
228: * it's parents and (grand+)parents with "MARK_PARENT", and
229: * all it's children and (grand+)children with "MARK_CHILD".
230: * <p>
231: * This does <b>not</b> set unrelated ProcessStatus data
232: * structures to "MARK_NONE" -- see <tt>unmark()</tt>.
233: *
234: * @see #getMark()
235: * @see #unmark()
236: */
237: public void mark() {
238: // mark self
239: this .mark = MARK_SELF;
240:
241: // mark parents
242: for (ProcessStatus p = this .parent; p != null; p = p.parent) {
243: p.mark = ProcessStatus.MARK_PARENT;
244: }
245:
246: // mark children
247: this .markChildren();
248: }
249:
250: // recursive!
251: private void markChildren() {
252: List cl = this .children;
253: int ncl = cl.size();
254: for (int i = 0; i < ncl; i++) {
255: ProcessStatus ci = (ProcessStatus) cl.get(i);
256: ci.mark = MARK_CHILD;
257: ci.markChildren();
258: }
259: }
260:
261: public String toString() {
262: return toString(true);
263: }
264:
265: public String toString(boolean showFullDetails) {
266: StringBuffer buf = new StringBuffer();
267:
268: buf.append("pid=").append(getProcessIdentifier());
269:
270: if (showFullDetails) {
271: buf.append(" mark=").append(getMarkAsString());
272:
273: buf.append(" parent={");
274: if (getParent() != null) {
275: buf.append(getParent().getProcessIdentifier());
276: }
277: buf.append("}");
278:
279: List c = getChildren();
280: int n = c.size();
281: buf.append(" children[").append(n).append("]={");
282: for (int i = 0; i < n; i++) {
283: ProcessStatus ci = (ProcessStatus) c.get(i);
284: buf.append(ci.getProcessIdentifier());
285: if (i < (n - 1)) {
286: buf.append(", ");
287: }
288: }
289: buf.append("}");
290:
291: buf.append(" ppid=").append(getParentProcessIdentifier());
292:
293: java.util.Date d = new java.util.Date(getStartTime());
294: buf.append(" start=\"").append(d).append("\"");
295:
296: buf.append(" user=\"").append(getUserName()).append("\"");
297: }
298:
299: buf.append(" cmd=\"").append(getCommand()).append("\"");
300:
301: return buf.toString();
302: }
303: }
|