KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > server > TCServerImpl


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.server;
6
7 import org.apache.commons.lang.StringUtils;
8 import org.mortbay.jetty.Server;
9 import org.mortbay.jetty.servlet.ServletHandler;
10 import org.mortbay.jetty.servlet.ServletHolder;
11 import org.mortbay.jetty.webapp.WebAppContext;
12
13 import EDU.oswego.cs.dl.util.concurrent.SynchronizedByte;
14
15 import com.tc.async.api.ConfigurationContext;
16 import com.tc.async.api.SEDA;
17 import com.tc.async.api.Sink;
18 import com.tc.async.api.Stage;
19 import com.tc.async.api.StageManager;
20 import com.tc.capabilities.AbstractCapabilitiesFactory;
21 import com.tc.config.schema.L2Info;
22 import com.tc.config.schema.NewCommonL2Config;
23 import com.tc.config.schema.NewSystemConfig;
24 import com.tc.config.schema.messaging.http.ConfigServlet;
25 import com.tc.config.schema.setup.ConfigurationSetupException;
26 import com.tc.config.schema.setup.L2TVSConfigurationSetupManager;
27 import com.tc.lang.StartupHelper;
28 import com.tc.lang.TCThreadGroup;
29 import com.tc.lang.ThrowableHandler;
30 import com.tc.lang.StartupHelper.StartupAction;
31 import com.tc.logging.CustomerLogging;
32 import com.tc.logging.TCLogger;
33 import com.tc.logging.TCLogging;
34 import com.tc.management.beans.L2MBeanNames;
35 import com.tc.management.beans.TCServerInfo;
36 import com.tc.net.protocol.tcm.CommunicationsManagerImpl;
37 import com.tc.net.protocol.transport.ConnectionPolicy;
38 import com.tc.net.protocol.transport.ConnectionPolicyImpl;
39 import com.tc.objectserver.core.impl.ServerManagementContext;
40 import com.tc.objectserver.impl.DistributedObjectServer;
41 import com.tc.stats.DSO;
42 import com.tc.stats.DSOMBean;
43 import com.tc.util.Assert;
44
45 import java.util.Date JavaDoc;
46
47 import javax.management.InstanceAlreadyExistsException JavaDoc;
48 import javax.management.MBeanRegistrationException JavaDoc;
49 import javax.management.MBeanServer JavaDoc;
50 import javax.management.NotCompliantMBeanException JavaDoc;
51
52 public class TCServerImpl extends SEDA implements TCServer {
53
54   private static final TCLogger logger = TCLogging.getLogger(TCServer.class);
55   private static final TCLogger consoleLogger = CustomerLogging.getConsoleLogger();
56   private static final byte STATE_STOPPED = 0;
57   private static final byte STATE_STARTED = 1;
58   private static final byte STATE_ACTIVE = 2;
59
60   private long startTime;
61   private long activateTime;
62
63   private CommunicationsManagerImpl commsManager;
64   private DistributedObjectServer dsoServer;
65   private Server httpServer;
66   private TerracottaConnector terracottaConnector;
67
68   private final Object JavaDoc stateLock = new Object JavaDoc();
69   private final SynchronizedByte state = new SynchronizedByte(STATE_STOPPED);
70
71   private final L2TVSConfigurationSetupManager configurationSetupManager;
72   private final ConnectionPolicy connectionPolicy;
73
74   /**
75    * This should only be used for tests.
76    */

77   public TCServerImpl(L2TVSConfigurationSetupManager configurationSetupManager) {
78     this(configurationSetupManager, new TCThreadGroup(new ThrowableHandler(TCLogging.getLogger(TCServer.class))));
79   }
80
81   public TCServerImpl(L2TVSConfigurationSetupManager configurationSetupManager, TCThreadGroup threadGroup) {
82     this(configurationSetupManager, threadGroup, new ConnectionPolicyImpl(Integer.MAX_VALUE));
83   }
84
85   public TCServerImpl(L2TVSConfigurationSetupManager manager, TCThreadGroup group, ConnectionPolicy connectionPolicy) {
86     super(group);
87     this.connectionPolicy = connectionPolicy;
88     Assert.assertNotNull(manager);
89     this.configurationSetupManager = manager;
90   }
91
92   public L2Info[] infoForAllL2s() {
93     String JavaDoc[] allKnownL2s = this.configurationSetupManager.allCurrentlyKnownServers();
94     L2Info[] out = new L2Info[allKnownL2s.length];
95
96     for (int i = 0; i < out.length; ++i) {
97       try {
98         NewCommonL2Config config = this.configurationSetupManager.commonL2ConfigFor(allKnownL2s[i]);
99
100         String JavaDoc name = allKnownL2s[i];
101         if (name == null) name = L2Info.IMPLICIT_L2_NAME;
102
103         String JavaDoc host = config.host().getString();
104         if (StringUtils.isBlank(host)) host = name;
105
106         out[i] = new L2Info(name, host, config.jmxPort().getInt());
107       } catch (ConfigurationSetupException cse) {
108         throw Assert.failure("This should be impossible here", cse);
109       }
110     }
111
112     return out;
113   }
114
115   public String JavaDoc getDescriptionOfCapabilities() {
116     return AbstractCapabilitiesFactory.getCapabilitiesManager().describe();
117   }
118
119   /**
120    * I realize this is wrong, since the server can still be starting but we'll have to deal with the whole stopping
121    * issue later, and there's the TCStop feature which should be removed.
122    */

123   public void stop() {
124     synchronized (stateLock) {
125       if (state.commit(STATE_ACTIVE, STATE_STOPPED)) {
126         stopServer();
127         logger.info("Server stopped.");
128       } else {
129         logger.warn("Server in incorrect state (" + state.get() + ") to be stopped.");
130       }
131     }
132
133   }
134
135   public void start() {
136     synchronized (stateLock) {
137       if (state.commit(STATE_STOPPED, STATE_STARTED)) {
138         try {
139           startServer();
140           if (!state.commit(STATE_STARTED, STATE_ACTIVE)) {
141             // formatting
142
throw new AssertionError JavaDoc("Server in incorrect state (" + state.get() + ") to be active.");
143           }
144         } catch (Throwable JavaDoc t) {
145           if(t instanceof RuntimeException JavaDoc) {
146             throw (RuntimeException JavaDoc)t;
147           }
148           throw new RuntimeException JavaDoc(t);
149         }
150       } else {
151         logger.warn("Server in incorrect state (" + state.get() + ") to be started.");
152       }
153     }
154   }
155
156   public void shutdown() {
157     synchronized (stateLock) {
158       if (!isStopped()) {
159         stop();
160       }
161       consoleLogger.info("Server exiting...");
162       System.exit(0);
163     }
164   }
165
166   public long getStartTime() {
167     return startTime;
168   }
169
170   public long getActivateTime() {
171     synchronized (stateLock) {
172       return activateTime;
173     }
174   }
175
176   public int getDSOListenPort() {
177     if (dsoServer != null) { return dsoServer.getListenPort(); }
178     throw new IllegalStateException JavaDoc("DSO Server not running");
179   }
180
181   public void dump() {
182     if (dsoServer != null) {
183       dsoServer.dump();
184     }
185   }
186
187   public DistributedObjectServer getDSOServer() {
188     return dsoServer;
189   }
190
191   public boolean isStarted() {
192     return state.compareTo(STATE_STARTED) == 0;
193   }
194
195   public boolean isActive() {
196     return state.compareTo(STATE_ACTIVE) == 0;
197   }
198
199   public boolean isStopped() {
200     return state.compareTo(STATE_STOPPED) == 0;
201   }
202
203   public String JavaDoc toString() {
204     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
205     buf.append("Server: ").append(super.toString()).append("\n");
206     if (isActive()) {
207       buf.append("Active since ").append(new Date JavaDoc(getStartTime())).append("\n");
208     } else if (isStarted()) {
209       buf.append("Started at ").append(new Date JavaDoc(getStartTime())).append("\n");
210     } else {
211       buf.append("Server is stopped").append("\n");
212     }
213
214     return buf.toString();
215   }
216
217   private void stopServer() {
218     // XXX: I have no idea if order of operations is correct here?
219

220     if (logger.isDebugEnabled()) {
221       consoleLogger.debug("Stopping TC server...");
222     }
223
224     if (commsManager != null) {
225       if (logger.isDebugEnabled()) {
226         logger.debug("Shutting down communications manager...");
227       }
228
229       try {
230         commsManager.shutdown();
231       } catch (Exception JavaDoc e) {
232         logger.error("Error shutting down comms manager", e);
233       } finally {
234         commsManager = null;
235       }
236     }
237
238     if (terracottaConnector != null) {
239       try {
240         terracottaConnector.shutdown();
241       } catch (Exception JavaDoc e) {
242         logger.error("Error shutting down terracotta connector", e);
243       } finally {
244         terracottaConnector = null;
245       }
246     }
247
248     try {
249       getStageManager().stopAll();
250     } catch (Exception JavaDoc e) {
251       logger.error("Error shutting down stage manager", e);
252     }
253
254     if (httpServer != null) {
255       if (logger.isDebugEnabled()) {
256         logger.debug("Shutting down HTTP server...");
257       }
258
259       try {
260         httpServer.stop();
261       } catch (Exception JavaDoc e) {
262         logger.error("Error shutting down HTTP server", e);
263       } finally {
264         httpServer = null;
265       }
266     }
267
268     // this stops the jmx server then dso server
269
if (dsoServer != null) {
270       try {
271         dsoServer.quickStop();
272       } catch (Exception JavaDoc e) {
273         logger.error("Error shutting down DSO server", e);
274       } finally {
275         dsoServer = null;
276       }
277     }
278
279   }
280
281   private class StartAction implements StartupAction {
282     public void execute() throws Throwable JavaDoc {
283       if (logger.isDebugEnabled()) {
284         logger.debug("Starting Terracotta server...");
285       }
286
287       startTime = System.currentTimeMillis();
288
289       NewSystemConfig systemConfig = TCServerImpl.this.configurationSetupManager.systemConfig();
290       terracottaConnector = new TerracottaConnector();
291       startHTTPServer(systemConfig, terracottaConnector);
292
293       Stage stage = getStageManager().createStage("dso-http-bridge", new HttpConnectionHandler(terracottaConnector), 1,
294                                                   100);
295       getStageManager().startAll(new NullContext(getStageManager()));
296
297       // the following code starts the jmx server as well
298
startDSOServer(stage.getSink());
299
300       activateTime = System.currentTimeMillis();
301
302       if (activationListener != null) {
303         activationListener.serverActivated(TCServerImpl.this);
304       }
305     }
306   }
307
308   protected void startServer() throws Exception JavaDoc {
309     new StartupHelper(getThreadGroup(), new StartAction()).startUp();
310   }
311
312   private void startDSOServer(Sink httpSink) throws Exception JavaDoc {
313     dsoServer = new DistributedObjectServer(configurationSetupManager, getThreadGroup(), connectionPolicy, httpSink,
314                                             new TCServerInfo(this));
315     dsoServer.start();
316
317     registerDSOServer();
318   }
319
320   private void startHTTPServer(NewSystemConfig systemConfig, TerracottaConnector tcConnector) throws Exception JavaDoc {
321     httpServer = new Server();
322     httpServer.addConnector(tcConnector);
323
324     WebAppContext context = new WebAppContext("", "/");
325     ServletHandler servletHandler = new ServletHandler();
326
327     /**
328      * We don't serve up any files, just hook in a few servlets. It's required the ResourceBase be non-null.
329      */

330     context.setResourceBase(System.getProperty("user.dir"));
331
332     ServletHolder holder;
333     holder = servletHandler.addServletWithMapping(VersionServlet.class.getName(), "/version");
334     servletHandler.addServlet(holder);
335
336     context.setAttribute(ConfigServlet.CONFIG_ATTRIBUTE, this.configurationSetupManager);
337     holder = servletHandler.addServletWithMapping(ConfigServlet.class.getName(), "/config");
338     servletHandler.addServlet(holder);
339
340     context.setServletHandler(servletHandler);
341     httpServer.addHandler(context);
342
343     try {
344       httpServer.start();
345     } catch (Exception JavaDoc e) {
346       consoleLogger.warn("Couldn't start HTTP server", e);
347       throw e;
348     }
349   }
350
351   private void registerDSOServer() throws InstanceAlreadyExistsException JavaDoc, MBeanRegistrationException JavaDoc,
352       NotCompliantMBeanException JavaDoc, NullPointerException JavaDoc {
353
354     ServerManagementContext mgmtContext = dsoServer.getManagementContext();
355     MBeanServer JavaDoc mBeanServer = dsoServer.getMBeanServer();
356     DSOMBean dso = new DSO(mgmtContext, mBeanServer);
357     mBeanServer.registerMBean(dso, L2MBeanNames.DSO);
358     mBeanServer.registerMBean(mgmtContext.getDSOAppEventsMBean(), L2MBeanNames.DSO_APP_EVENTS);
359   }
360
361   private TCServerActivationListener activationListener;
362
363   public void setActivationListener(TCServerActivationListener listener) {
364     activationListener = listener;
365   }
366
367   private static class NullContext implements ConfigurationContext {
368
369     private final StageManager manager;
370
371     public NullContext(StageManager manager) {
372       this.manager = manager;
373     }
374
375     public TCLogger getLogger(Class JavaDoc clazz) {
376       return TCLogging.getLogger(clazz);
377     }
378
379     public Stage getStage(String JavaDoc name) {
380       return manager.getStage(name);
381     }
382
383   }
384
385 }
386
Popular Tags