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 org.cougaar.core.service.SuicideService;
030:
031: import org.cougaar.core.agent.Agent;
032: import org.cougaar.core.agent.service.alarm.Alarm;
033: import org.cougaar.core.agent.service.alarm.ExecutionTimer;
034: import org.cougaar.core.agent.service.alarm.RealTimer;
035: import org.cougaar.core.agent.service.alarm.Timer;
036: import org.cougaar.core.component.ServiceBroker;
037: import org.cougaar.core.component.ServiceProvider;
038: import org.cougaar.core.component.BindingSite;
039: import org.cougaar.core.component.Component;
040: import org.cougaar.core.node.NodeControlService;
041: import org.cougaar.util.GenericStateModelAdapter;
042: import org.cougaar.util.log.Logger;
043: import org.cougaar.util.log.Logging;
044:
045: /**
046: * This component advertises the {@link SuicideService}.
047: */
048: public final class SuicideServiceComponent extends
049: GenericStateModelAdapter implements Component {
050:
051: private static final Logger log = Logging
052: .getLogger(SuicideService.class);
053:
054: private ServiceBroker rootsb;
055:
056: private ServiceProvider ssp;
057: private SuicideService ssi;
058: private static SuicideService singleton;
059:
060: private SuicideMonitor monitor;
061:
062: public void setNodeControlService(NodeControlService ncs) {
063: rootsb = (ncs == null ? null : ncs.getRootServiceBroker());
064: }
065:
066: public void load() {
067: super .load();
068: ssp = new SuicideServiceProvider();
069: ssi = new SuicideServiceImpl();
070: setSingleton(ssi);
071: rootsb.addService(SuicideService.class, ssp);
072: if (log.isDebugEnabled()) {
073: log.error("SuicideService loaded");
074: }
075: }
076:
077: public void start() {
078: super .start();
079: if (SuicideService.isSuicideEnabled) {
080: if (SuicideService.isProactiveEnabled) {
081: monitor = new SuicideMonitor();
082: monitor.start();
083: }
084: }
085: }
086:
087: public void stop() {
088: if (SuicideService.isSuicideEnabled) {
089: if (SuicideService.isProactiveEnabled) {
090: monitor.stop();
091: monitor = null;
092: }
093: }
094: super .stop();
095: }
096:
097: public void unload() {
098: rootsb.revokeService(SuicideService.class, ssp);
099: ssp = null;
100: ssi = null;
101: super .unload();
102: }
103:
104: private class SuicideServiceProvider implements ServiceProvider {
105: public Object getService(ServiceBroker xsb, Object requestor,
106: Class serviceClass) {
107: if (serviceClass == SuicideService.class) {
108: return ssi;
109: }
110: return null;
111: }
112:
113: public void releaseService(ServiceBroker xsb, Object requestor,
114: Class serviceClass, Object service) {
115: }
116: }
117:
118: private class SuicideServiceImpl implements SuicideService {
119: public void die(Object component, Throwable error) {
120: if (error == null)
121: throw new IllegalArgumentException(
122: "May not Suicide without an Error");
123: try {
124: String s = (component == null) ? "anonymous"
125: : (component.toString());
126: log.fatal("Suicide from " + s, error);
127: StateDumpService sds = (StateDumpService) rootsb
128: .getService(this , StateDumpService.class, null);
129: if (sds != null)
130: sds.dumpState();
131: } finally {
132: if (SuicideService.isSuicideEnabled) {
133: System.exit(SuicideService.EXIT_CODE);
134: }
135: }
136: }
137: }
138:
139: public static synchronized SuicideService getSuicideService() {
140: return singleton;
141: }
142:
143: private static synchronized void setSingleton(SuicideService ss) {
144: if (singleton != null) {
145: log.error(
146: "Multiple SuicideService instances loaded into VM",
147: new Throwable());
148: } else {
149: singleton = ss;
150: }
151: }
152:
153: private class SuicideMonitor implements Runnable {
154: Thread t;
155: Runtime runtime;
156: long thresh;
157: long period;
158:
159: SuicideMonitor() {
160: runtime = Runtime.getRuntime();
161: double lm = SuicideService.lowMem;
162: if (lm >= 1.0) {
163: thresh = (long) (lm * 1024);
164: } else {
165: thresh = (long) ((double) runtime.maxMemory() * lm);
166: }
167: period = (long) (SuicideService.proactivePeriod * 1000L);
168: }
169:
170: void start() {
171: t = new Thread(this );
172: t.start();
173: }
174:
175: void stop() {
176: t.interrupt();
177: t = null;
178: }
179:
180: public void run() {
181: try {
182: while (!Thread.currentThread().isInterrupted()) {
183: Thread.sleep(period);
184: checkForOOM();
185: }
186: } catch (InterruptedException ie) {
187: Thread.interrupted();
188: // exit thread...
189: }
190: }
191:
192: void checkForOOM() {
193: long fm = runtime.freeMemory();
194: long mm = runtime.maxMemory();
195: long tm = runtime.totalMemory();
196: long headroom = fm + (mm - tm); // how much heap space might be left
197: if (headroom < thresh) {
198: ssi.die(null, new Error(
199: "Looming OutOfMemoryError (only " + headroom
200: + " of " + mm + " remaining, total="
201: + tm + ", free=" + fm + ")"));
202: }
203: }
204: }
205: }
|