001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.management.beans.object;
005:
006: import com.tc.logging.TCLogger;
007: import com.tc.logging.TCLogging;
008: import com.tc.management.AbstractTerracottaMBean;
009:
010: import javax.management.NotCompliantMBeanException;
011:
012: public class ObjectManagementMonitor extends AbstractTerracottaMBean
013: implements ObjectManagementMonitorMBean {
014:
015: private static final TCLogger logger = TCLogging
016: .getLogger(ObjectManagementMonitor.class);
017:
018: private volatile GCComptroller gcController;
019:
020: private final GCRunner gcRunner;
021:
022: public ObjectManagementMonitor() throws NotCompliantMBeanException {
023: super (ObjectManagementMonitorMBean.class, false);
024:
025: gcRunner = new GCRunner() {
026: private boolean isRunning = false;
027:
028: public void run() {
029: setRunningState();
030: gcController.startGC();
031: setStopState();
032: }
033:
034: private synchronized void setRunningState() {
035: if (isRunning) {
036: throw new UnsupportedOperationException(
037: "Cannot run GC because GC is already running.");
038: }
039: isRunning = true;
040: logger.info("Running GC.");
041: }
042:
043: private synchronized void setStopState() {
044: if (!isRunning) {
045: throw new UnsupportedOperationException(
046: "Cannot stop GC because GC is not running.");
047: }
048: isRunning = false;
049: logger.info("GC finished.");
050: }
051:
052: public synchronized boolean isGCRunning() {
053: return isRunning;
054: }
055: };
056: }
057:
058: public boolean isGCRunning() {
059: return gcRunner.isGCRunning();
060: }
061:
062: public synchronized void runGC() {
063: if (!isEnabled()) {
064: throw new UnsupportedOperationException(
065: "Cannot run GC because mBean is not enabled.");
066: }
067: if (gcController == null) {
068: throw new RuntimeException(
069: "Failure: see log for more information");
070: }
071: if (gcController.gcEnabledInConfig()) {
072: throw new UnsupportedOperationException(
073: "Cannot run GC externally because GC is enabled through config.");
074: }
075: if (!gcController.isGCStarted()) {
076: throw new UnsupportedOperationException(
077: "Cannot run GC externally because this server "
078: + "is in PASSIVE state and GC is disabled.");
079: }
080: // XXX::Note:: There is potencially a rare here, one could check to see
081: // if it is disabled and before GC is started it could be disabled. In
082: // which case it will not be run, just logged in the log file.
083: if (gcController.isGCDisabled()) {
084: throw new UnsupportedOperationException(
085: "Cannot run GC externally because PASSIVE server(s) are currently synching state "
086: + "with this ACTIVE server and GC is disabled.");
087: }
088: if (isGCRunning()) {
089: throw new UnsupportedOperationException(
090: "Cannot run GC because GC is already running.");
091: }
092:
093: Thread gcRunnerThread = new Thread(gcRunner);
094: gcRunnerThread.setName("GCRunnerThread");
095: gcRunnerThread.start();
096: }
097:
098: public synchronized void reset() {
099: // nothing to reset
100: }
101:
102: public void registerGCController(GCComptroller controller) {
103: if (isEnabled()) {
104: if (gcController != null) {
105: logger
106: .warn("Registering new gc-controller while one already registered. Old : "
107: + gcController);
108: }
109: gcController = controller;
110: }
111: }
112:
113: public static interface GCComptroller {
114: void startGC();
115:
116: boolean gcEnabledInConfig();
117:
118: boolean isGCDisabled();
119:
120: boolean isGCStarted();
121: }
122:
123: static interface GCRunner extends Runnable {
124: boolean isGCRunning();
125: }
126: }
|