001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.management.beans;
006:
007: import com.tc.config.schema.L2Info;
008: import com.tc.l2.context.StateChangedEvent;
009: import com.tc.l2.state.StateChangeListener;
010: import com.tc.l2.state.StateManager;
011: import com.tc.management.AbstractTerracottaMBean;
012: import com.tc.server.TCServer;
013: import com.tc.util.ProductInfo;
014: import com.tc.util.State;
015:
016: import java.util.Timer;
017: import java.util.TimerTask;
018:
019: import javax.management.AttributeChangeNotification;
020: import javax.management.MBeanNotificationInfo;
021: import javax.management.NotCompliantMBeanException;
022:
023: public class TCServerInfo extends AbstractTerracottaMBean implements
024: TCServerInfoMBean, StateChangeListener {
025: private static final boolean DEBUG = false;
026:
027: private static final MBeanNotificationInfo[] NOTIFICATION_INFO;
028: static {
029: final String[] notifTypes = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
030: final String name = AttributeChangeNotification.class.getName();
031: final String description = "An attribute of this MBean has changed";
032: NOTIFICATION_INFO = new MBeanNotificationInfo[] { new MBeanNotificationInfo(
033: notifTypes, name, description) };
034: }
035:
036: private final TCServer server;
037: private final ProductInfo productInfo;
038: private final String buildID;
039: private final L2State l2State;
040: private final StateChangeNotificationInfo stateChangeNotificationInfo;
041: private long nextSequenceNumber;
042:
043: public TCServerInfo(final TCServer server, final L2State l2State)
044: throws NotCompliantMBeanException {
045: super (TCServerInfoMBean.class, true);
046: this .server = server;
047: this .l2State = l2State;
048: this .l2State.registerStateChangeListener(this );
049: productInfo = ProductInfo.getInstance();
050: buildID = makeBuildID(productInfo);
051: nextSequenceNumber = 1;
052: stateChangeNotificationInfo = new StateChangeNotificationInfo();
053: }
054:
055: public void reset() {
056: // nothing to reset
057: }
058:
059: public boolean isStarted() {
060: return l2State.isStartState();
061: }
062:
063: public boolean isActive() {
064: return l2State.isActiveCoordinator();
065: }
066:
067: public boolean isPassiveUninitialized() {
068: return l2State.isPassiveUninitialized();
069: }
070:
071: public boolean isPassiveStandby() {
072: return l2State.isPassiveStandby();
073: }
074:
075: public long getStartTime() {
076: return server.getStartTime();
077: }
078:
079: public long getActivateTime() {
080: return server.getActivateTime();
081: }
082:
083: public void stop() {
084: server.stop();
085: _sendNotification("TCServer stopped", "Started",
086: "jmx.terracotta.L2.stopped", Boolean.TRUE,
087: Boolean.FALSE);
088: }
089:
090: public boolean isShutdownable() {
091: return server.canShutdown();
092: }
093:
094: /**
095: * This schedules the shutdown to occur one second after we return from this call because otherwise JMX will be
096: * shutdown and we'll get all sorts of other errors trying to return from this call.
097: */
098: public void shutdown() {
099: if (!server.canShutdown()) {
100: throw new RuntimeException(
101: "Server cannot be shutdown because it is not fully started.");
102: }
103: final Timer timer = new Timer();
104: final TimerTask task = new TimerTask() {
105: public void run() {
106: server.shutdown();
107: }
108: };
109: timer.schedule(task, 1000);
110: }
111:
112: public MBeanNotificationInfo[] getNotificationInfo() {
113: return NOTIFICATION_INFO;
114: }
115:
116: public void startBeanShell(int port) {
117: server.startBeanShell(port);
118: }
119:
120: public String toString() {
121: if (isStarted()) {
122: return "starting, startTime(" + getStartTime() + ")";
123: } else if (isActive()) {
124: return "active, activateTime(" + getActivateTime() + ")";
125: } else {
126: return "stopped";
127: }
128: }
129:
130: public String getVersion() {
131: return productInfo.toShortString();
132: }
133:
134: public String getBuildID() {
135: return buildID;
136: }
137:
138: public String getCopyright() {
139: return productInfo.copyright();
140: }
141:
142: public String getDescriptionOfCapabilities() {
143: return server.getDescriptionOfCapabilities();
144: }
145:
146: public L2Info[] getL2Info() {
147: return server.infoForAllL2s();
148: }
149:
150: private static String makeBuildID(final ProductInfo productInfo) {
151: String timeStamp = productInfo.buildTimestampAsString();
152: String revision = productInfo.buildRevision();
153: String user = productInfo.buildUser();
154: String host = productInfo.buildHost();
155: String branch = productInfo.buildBranch();
156: return timeStamp + " (" + revision + " by " + user + "@" + host
157: + " from " + branch + ")";
158: }
159:
160: public String getHealthStatus() {
161: // FIXME: the returned value should eventually contain a true representative status of L2 server.
162: // for now just return 'OK' to indicate that the process is up-and-running..
163: return "OK";
164: }
165:
166: public void l2StateChanged(StateChangedEvent sce) {
167: State state = sce.getCurrentState();
168:
169: if (l2State.getState().equals(StateManager.ACTIVE_COORDINATOR)) {
170: server.updateActivateTime();
171: }
172:
173: debugPrintln("***** msg=["
174: + stateChangeNotificationInfo.getMsg(state)
175: + "] attrName=["
176: + stateChangeNotificationInfo.getAttributeName(state)
177: + "] attrType=["
178: + stateChangeNotificationInfo.getAttributeType(state)
179: + "] stateName=[" + state.getName() + "]");
180:
181: _sendNotification(stateChangeNotificationInfo.getMsg(state),
182: stateChangeNotificationInfo.getAttributeName(state),
183: stateChangeNotificationInfo.getAttributeType(state),
184: Boolean.FALSE, Boolean.TRUE);
185: }
186:
187: private synchronized void _sendNotification(String msg,
188: String attr, String type, Object oldVal, Object newVal) {
189: sendNotification(new AttributeChangeNotification(this ,
190: nextSequenceNumber++, System.currentTimeMillis(), msg,
191: attr, type, oldVal, newVal));
192: }
193:
194: private void debugPrintln(String s) {
195: if (DEBUG) {
196: System.err.println(s);
197: }
198: }
199: }
|