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 org.cougaar.core.service.ThreadService;
030: import org.cougaar.util.log.Logger;
031: import org.cougaar.util.log.Logging;
032:
033: /**
034: * An optional utility class for use by {@link java.lang.Runnable}s
035: * running in a pooled {@link org.cougaar.core.service.ThreadService}
036: * thread to tell the {@link ThreadService} why they are running
037: * so long (for example, due to a blocking I/O call).
038: * <p>
039: * For example:<pre>
040: * try {
041: * SchedulableStatus.beginNetIO("download url");
042: * // open a URLConnection, read from socket, etc.
043: * } finally {
044: * SchedulableStatus.endBlocking();
045: * }
046: * </pre>
047: * <p>
048: * This information is shown in the {@link TopPlugin}'s "/threads/top"
049: * servlet.
050: */
051: public final class SchedulableStatus {
052: public static final int NOT_BLOCKING = -1;
053: public static final int OTHER = 0;
054: public static final int WAIT = 1;
055: public static final int FILEIO = 2;
056: public static final int NETIO = 3;
057: public static final int CPUINTENSIVE = 4;
058:
059: private static Logger logger = Logging
060: .getLogger("org.cougaar.core.thread.SchedulableStatus");
061:
062: private static boolean checkLegalBlocking(int type,
063: SchedulableObject schedulable) {
064: int lane = schedulable.getLane();
065: switch (lane) {
066: case ThreadService.BEST_EFFORT_LANE:
067: return true;
068:
069: case ThreadService.WILL_BLOCK_LANE:
070: return true;
071:
072: case ThreadService.CPU_INTENSE_LANE:
073: if (type == WAIT || type == CPUINTENSIVE)
074: return true;
075: if (logger.isWarnEnabled())
076: logger
077: .warn(schedulable.getName()
078: + " is in CPU_INTENSE_LANE but is blocking on "
079: + statusString(type, ""));
080: return false;
081:
082: case ThreadService.WELL_BEHAVED_LANE:
083: if (type == WAIT)
084: return true;
085: if (logger.isWarnEnabled())
086: logger
087: .warn(schedulable.getName()
088: + " is in WELL_BEHAVED_LANE but is blocking on "
089: + statusString(type, ""));
090: return false;
091:
092: default:
093: return true;
094: }
095: }
096:
097: public static void beginBlocking(int type, String excuse) {
098: Thread thread = Thread.currentThread();
099: if (thread instanceof ThreadPool.PooledThread) {
100: ThreadPool.PooledThread pthread = (ThreadPool.PooledThread) thread;
101: SchedulableObject sched = pthread.getSchedulable();
102: checkLegalBlocking(type, sched);
103: sched.setBlocking(type, excuse == null ? "No excuse given"
104: : excuse);
105: }
106: }
107:
108: public static void beginWait(String excuse) {
109: beginBlocking(WAIT, excuse);
110: }
111:
112: public static void beginFileIO(String excuse) {
113: beginBlocking(FILEIO, excuse);
114: }
115:
116: public static void beginNetIO(String excuse) {
117: beginBlocking(NETIO, excuse);
118: }
119:
120: public static void beginCPUIntensive(String excuse) {
121: beginBlocking(NETIO, excuse);
122: }
123:
124: public static void endBlocking() {
125: Thread thread = Thread.currentThread();
126: if (thread instanceof ThreadPool.PooledThread) {
127: ThreadPool.PooledThread pthread = (ThreadPool.PooledThread) thread;
128: SchedulableObject sched = pthread.getSchedulable();
129: sched.clearBlocking();
130: }
131: }
132:
133: public static void withBlocking(int type, String excuse,
134: Runnable thunk) {
135: try {
136: beginBlocking(type, excuse);
137: thunk.run();
138: } finally {
139: endBlocking();
140: }
141: }
142:
143: public static void withWait(String excuse, Runnable thunk) {
144: withBlocking(WAIT, excuse, thunk);
145: }
146:
147: public static void withFileIO(String excuse, Runnable thunk) {
148: withBlocking(FILEIO, excuse, thunk);
149: }
150:
151: public static void withNetIO(String excuse, Runnable thunk) {
152: withBlocking(NETIO, excuse, thunk);
153: }
154:
155: public static void withCPUIntensive(String excuse, Runnable thunk) {
156: withBlocking(CPUINTENSIVE, excuse, thunk);
157: }
158:
159: public static String statusString(int type, String excuse) {
160: String string = excuse;
161: switch (type) {
162: case NOT_BLOCKING:
163: string = "none";
164: break;
165: case OTHER:
166: break;
167: case WAIT:
168: string = "Lock wait: " + string;
169: break;
170: case FILEIO:
171: string = "Disk I/O: " + string;
172: break;
173: case NETIO:
174: string = "Network I/O: " + string;
175: break;
176: case CPUINTENSIVE:
177: string = "CPU Intensive: " + string;
178: break;
179: }
180: return string;
181: }
182:
183: }
|