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.thread;
028:
029: import java.util.Timer;
030: import java.util.TimerTask; // imported only for javadoc
031:
032: import org.cougaar.core.component.ParameterizedComponent;
033: import org.cougaar.core.component.ServiceBroker;
034: import org.cougaar.core.service.ThreadService;
035:
036: /**
037: * This component is used to create the TopServlet, which it will do
038: * unless the "servlet" parameter is set to "false", and the
039: * RogueThreadDetector, which it will do unless the "detector"
040: * parameter is set to "false".
041: *
042: * The servlet displays a more or less current list of {@link
043: * Schedulable}s, both running and queued, at all levels and for all
044: * lanes, in a way that's vaguely remniscent of the unix 'top'
045: * command. The access path is <b>/threads/top</b>.
046: *
047: * The RogueThreadDetector is a {@link TimerTask} running a {@link
048: * Timer} (i.e., it does not use the {@link ThreadService}). Its
049: * function is to log {@link Schedulable}s that have been running too long.
050: * The period of the task defaults to 5000 and can be set to some
051: * other value with the "period" value.
052: *
053: *
054: * As if that weren't enough, it can also be used for yet another
055: * purpose, to run a test of the RogueThreadDetector, which it
056: * exercises by running a {@link Schedulable} that intentionally runs
057: * for too long. To enable this test, set the "test" parameter to
058: * "true".
059: *
060: * This is designed to be a Node-level plugin.
061: */
062: public class TopPlugin extends ParameterizedComponent // not a Plugin
063: {
064: private static final long DEFAULT_SAMPLE_PERIOD = 5000;
065: private static final String WARN_TIME_VALUE = "100";
066: private static final String WARN_TIME_PARAM = "warn-time";
067: private static final String INFO_TIME_VALUE = "10";
068: private static final String INFO_TIME_PARAM = "info-time";
069:
070: private RogueThreadDetector rtd;
071: private ServiceBroker sb;
072: private Timer timer;
073:
074: public TopPlugin() {
075: super ();
076: }
077:
078: public void setServiceBroker(ServiceBroker sb) {
079: this .sb = sb;
080: }
081:
082: public void load() {
083: super .load();
084:
085: String run_servlet = getParameter("servlet", "true");
086: String run_timer = getParameter("detector", "true");
087: long sample_period = getParameter("period",
088: DEFAULT_SAMPLE_PERIOD);
089: String test = getParameter("test", "false");
090: ServiceBroker sb = getServiceBroker();
091: if (run_servlet.equalsIgnoreCase("true")) {
092: new TopServlet(sb);
093: }
094: if (run_timer.equalsIgnoreCase("true")) {
095: rtd = new RogueThreadDetector(sb, sample_period);
096:
097: // initialize param subscriptions
098: // initializeParameter(WARN_TIME_PARAM,WARN_TIME_VALUE);
099: // initializeParameter(INFO_TIME_PARAM,INFO_TIME_VALUE);
100: dynamicParameterChanged(WARN_TIME_PARAM, getParameter(
101: WARN_TIME_PARAM, WARN_TIME_VALUE));
102: dynamicParameterChanged(INFO_TIME_PARAM, getParameter(
103: INFO_TIME_PARAM, INFO_TIME_VALUE));
104:
105: // We can't use the ThreadService for the poller because it
106: // may run out of pooled threads, which is what we are trying
107: // to detect.
108: timer = new Timer(true);
109: timer.schedule(rtd, 0, sample_period);
110: }
111: if (test.equalsIgnoreCase("true")) {
112: long lane = getParameter("lane",
113: ThreadService.BEST_EFFORT_LANE);
114: runTest((int) lane);
115: }
116: }
117:
118: public void unload() {
119: if (rtd != null) {
120: rtd.cancel();
121: rtd = null;
122: }
123: if (timer != null) {
124: timer.cancel();
125: timer = null;
126: }
127: super .unload();
128: }
129:
130: protected void dynamicParameterChanged(String name, String value) {
131: if (name.equals(WARN_TIME_PARAM)) {
132: int warnTime = Integer.parseInt(value) * 1000; //millisecond
133: rtd.setWarnTime(warnTime);
134: } else if (name.equals(INFO_TIME_PARAM)) {
135: int infoTime = Integer.parseInt(value) * 1000; //millisecond
136: rtd.setInfoTime(infoTime);
137: }
138: }
139:
140: void runTest(int lane) {
141: Runnable test = new Runnable() {
142: public void run() {
143: int type = SchedulableStatus.CPUINTENSIVE;
144: String excuse = "Calls to sleep() are evil";
145: SchedulableStatus.beginBlocking(type, excuse);
146: try {
147: Thread.sleep(100000);
148: } catch (InterruptedException ex) {
149: }
150: SchedulableStatus.endBlocking();
151: }
152: };
153: ServiceBroker sb = getServiceBroker();
154: ThreadService tsvc = (ThreadService) sb.getService(this ,
155: ThreadService.class, null);
156: org.cougaar.core.thread.Schedulable sched = tsvc.getThread(
157: this , test, "Sleep test", lane);
158: sb.releaseService(this , ThreadService.class, tsvc);
159: sched.schedule(0, 10);
160: }
161:
162: public ServiceBroker getServiceBroker() {
163: return sb;
164: }
165:
166: }
|