001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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:
027: package org.cougaar.core.node;
028:
029: import java.io.FileInputStream;
030: import java.io.PrintStream;
031: import java.util.Collection;
032: import java.util.Iterator;
033: import java.util.List;
034: import java.util.Properties;
035:
036: import org.cougaar.bootstrap.SystemProperties;
037: import org.cougaar.core.component.BindingSite;
038: import org.cougaar.core.component.ParameterizedComponent;
039: import org.cougaar.core.component.ServiceBroker;
040: import org.cougaar.core.component.ServiceProvider;
041: import org.cougaar.core.mts.MessageAddress;
042: import org.cougaar.core.service.BlackboardQueryService;
043: import org.cougaar.core.service.SuicideService;
044: import org.cougaar.core.thread.CougaarThread;
045: import org.cougaar.core.thread.Schedulable;
046: import org.cougaar.core.thread.ThreadStatusService;
047: import org.cougaar.core.util.UniqueObject;
048: import org.cougaar.core.mts.MessageQueueDumpService;
049: import org.cougaar.util.UnaryPredicate;
050: import org.cougaar.util.log.Logger;
051: import org.cougaar.util.log.Logging;
052:
053: public final class StateDumpServiceComponent extends
054: ParameterizedComponent implements ServiceProvider {
055: private static Logger logger = Logging
056: .getLogger(StateDumpServiceComponent.class);
057: private ServiceBroker sb, rootsb;
058: private Impl impl;
059: private int waitTime;
060:
061: public StateDumpServiceComponent() {
062: }
063:
064: public void setNodeControlService(NodeControlService ncs) {
065: rootsb = (ncs == null) ? null : ncs.getRootServiceBroker();
066: }
067:
068: public void load() {
069: super .load();
070: impl = new Impl(sb);
071: rootsb.addService(StateDumpService.class, this );
072: }
073:
074: public void start() {
075: super .start();
076: waitTime = (int) getParameter("waitTime", 10000);
077: impl.threadStatus = (ThreadStatusService) sb.getService(this ,
078: ThreadStatusService.class, null);
079: // test for forcing Suicide
080: int dieTime = (int) getParameter("dieTime", 0);
081: if (dieTime > 0) {
082: java.util.Timer timer = new java.util.Timer();
083: java.util.TimerTask task = new java.util.TimerTask() {
084: public void run() {
085: SuicideService svc = (SuicideService) sb
086: .getService(this , SuicideService.class,
087: null);
088: Throwable thr = new Error("Pointless suicide");
089: svc.die(StateDumpServiceComponent.this , thr);
090: }
091: };
092: timer.schedule(task, dieTime);
093: }
094: }
095:
096: public Object getService(ServiceBroker sb, Object requestor,
097: Class serviceClass) {
098: if (serviceClass == StateDumpService.class)
099: return impl;
100: else
101: return null;
102: }
103:
104: public void releaseService(ServiceBroker sb, Object requestor,
105: Class serviceClass, Object service) {
106: }
107:
108: public final void setBindingSite(BindingSite bs) {
109: this .sb = bs.getServiceBroker();
110: }
111:
112: private class Impl implements StateDumpService,
113: ThreadStatusService.Body {
114: ThreadStatusService threadStatus;
115: MessageQueueDumpService mqds;
116: ServiceBroker sb;
117:
118: Impl(ServiceBroker sb) {
119: this .sb = sb;
120: }
121:
122: private String getTopJavaPid(Properties props) {
123: String last_pid = props.getProperty("PPid");
124: String previous_pid = props.getProperty("Pid");
125: try {
126: FileInputStream fis = new FileInputStream("/proc/"
127: + last_pid + "/status");
128: props.load(fis);
129: String name = props.getProperty("Name");
130: if (name.equals("java")) {
131: return getTopJavaPid(props);
132: } else {
133: return previous_pid;
134: }
135: } catch (Exception ex) {
136: logger.error(null, ex);
137: return null;
138: }
139: }
140:
141: private String getTopJavaPid() {
142: Properties props = new Properties();
143: props.setProperty("PPid", "self");
144: return getTopJavaPid(props);
145: }
146:
147: private void dumpThreads() {
148: // Only works in Linux
149: String os_name = SystemProperties.getProperty("os.name");
150: if (!os_name.equals("Linux")) {
151: logger.warn("Can't find pid to dump threads in "
152: + os_name);
153: return;
154: }
155: logger.warn("Dumping Java Threads");
156: String pid = getTopJavaPid();
157: if (pid != null) {
158: String command = "kill -3 " + pid;
159: logger.warn(command);
160: try {
161: Runtime.getRuntime().exec(command);
162: } catch (Exception ex) {
163: logger.error(null, ex);
164: }
165: }
166: }
167:
168: public void run(String scheduler, Schedulable schedulable) {
169: int state = schedulable.getState();
170: String state_string = null;
171: if (state == CougaarThread.THREAD_PENDING)
172: state_string = "Queued";
173: else if (state == CougaarThread.THREAD_RUNNING)
174: state_string = "Running";
175: else
176: return; // skip dormant Schedulables
177:
178: long elapsed = System.currentTimeMillis()
179: - schedulable.getTimestamp();
180:
181: logger.warn("Schedulable " + " " + state_string + " "
182: + elapsed + " " + scheduler + " "
183: + schedulable.getLane() + " "
184: + schedulable.getName() + " "
185: + schedulable.getConsumer());
186: }
187:
188: private void dumpSchedulables() {
189: logger.warn("Dumping Schedulables");
190: int count = threadStatus.iterateOverStatus(this );
191: logger.warn("Dumped " + count + " Schedulables");
192: }
193:
194: private void dumpQueues() {
195: if (mqds == null) {
196: mqds = (MessageQueueDumpService) sb.getService(this ,
197: MessageQueueDumpService.class, null);
198: if (mqds == null) {
199: logger.warn("Couldn't get MessageQueueDumpService");
200: return;
201: }
202: }
203:
204: logger.warn("Dumping Message Queues");
205: int count = mqds.dumpQueues(logger);
206: logger.warn("Dumped " + count + " Messages");
207: }
208:
209: private void dumpMemoryProfile() {
210: PrintStream out = System.out;
211: try {
212: Class cl = Class.forName("org.cougaar.profiler.Dump");
213: Class[] params = { PrintStream.class };
214: Object[] args = { out };
215: java.lang.reflect.Method m = cl.getMethod("dumpTo",
216: params);
217: m.invoke(null, args);
218: } catch (Exception e) {
219: logger.warn("Memory Profiler not found: " + e);
220: }
221: }
222:
223: private void dumpObject(UniqueObject object) {
224: logger.warn(object.toString());
225: }
226:
227: private void dumpBlackboard() {
228: BlackboardQueryService svc = (BlackboardQueryService) sb
229: .getService(this , BlackboardQueryService.class,
230: null);
231: if (svc != null) {
232: UnaryPredicate pred = new UnaryPredicate() {
233: public boolean execute(Object o) {
234: return (o instanceof UniqueObject);
235: }
236: };
237: Collection objects = svc.query(pred);
238: Iterator itr = objects.iterator();
239: logger.warn("Dumping " + objects.size()
240: + " Blackboard objects");
241: while (itr.hasNext()) {
242: UniqueObject object = (UniqueObject) itr.next();
243: dumpObject(object);
244: }
245: } else {
246: logger.warn("Couldn't get BlackboardQueryService");
247: }
248: }
249:
250: public void dumpState() {
251: try {
252: dumpSchedulables();
253: dumpQueues();
254: dumpBlackboard();
255: dumpMemoryProfile();
256: dumpThreads();
257: } catch (Throwable any) {
258: logger.error(null, any);
259: }
260: // Give dumpers time to catch up
261: logger.warn("waiting " + waitTime / 1000 + " seconds");
262: try {
263: Thread.sleep(waitTime);
264: } catch (InterruptedException ex) {
265: }
266: }
267: }
268:
269: }
|