KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > cluster > Cluster


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.cluster;
31
32 import com.caucho.config.BuilderProgram;
33 import com.caucho.config.BuilderProgramContainer;
34 import com.caucho.config.Config;
35 import com.caucho.config.ConfigException;
36 import com.caucho.config.SchemaBean;
37 import com.caucho.config.types.InitProgram;
38 import com.caucho.config.types.Period;
39 import com.caucho.jmx.Jmx;
40 import com.caucho.loader.DynamicClassLoader;
41 import com.caucho.loader.Environment;
42 import com.caucho.loader.EnvironmentBean;
43 import com.caucho.loader.EnvironmentClassLoader;
44 import com.caucho.loader.EnvironmentListener;
45 import com.caucho.loader.EnvironmentLocal;
46 import com.caucho.management.server.ClusterMXBean;
47 import com.caucho.server.port.Port;
48 import com.caucho.server.resin.Resin;
49 import com.caucho.util.L10N;
50 import com.caucho.vfs.Path;
51 import com.caucho.vfs.Vfs;
52
53 import javax.annotation.PostConstruct;
54 import javax.management.ObjectName JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.logging.Level JavaDoc;
57 import java.util.logging.Logger JavaDoc;
58
59 /**
60  * Defines a set of clustered servers.
61  */

62 public class Cluster
63   implements EnvironmentListener, EnvironmentBean, SchemaBean
64 {
65   private static final L10N L = new L10N(ClusterGroup.class);
66   private static final Logger JavaDoc log = Logger.getLogger(Cluster.class.getName());
67
68   static protected final EnvironmentLocal<String JavaDoc> _serverIdLocal
69     = new EnvironmentLocal<String JavaDoc>("caucho.server-id");
70
71   static protected final EnvironmentLocal<Cluster> _clusterLocal
72     = new EnvironmentLocal<Cluster>("caucho.cluster");
73
74   private String JavaDoc _id = "";
75
76   private String JavaDoc _serverId = "";
77
78   private EnvironmentClassLoader _classLoader;
79   
80   private Resin _resin;
81
82   private Path _rootDirectory;
83
84   private ClusterAdmin _admin;
85   private ObjectName JavaDoc _objectName;
86
87   private ArrayList JavaDoc<InitProgram> _serverDefaultList
88     = new ArrayList JavaDoc<InitProgram>();
89
90   private ArrayList JavaDoc<ClusterServer> _serverList
91     = new ArrayList JavaDoc<ClusterServer>();
92
93   private ClusterServer[] _serverArray = new ClusterServer[0];
94
95   private ClusterGroup _group;
96
97   private StoreManager _clusterStore;
98
99   // compatibility with 3.0
100
private long _clientMaxIdleTime = 30000L;
101   private long _clientFailRecoverTime = 15000L;
102   private long _clientWarmupTime = 60000L;
103   private long _clientBusyTime = 15000L;
104   
105   private long _clientReadTimeout = 60000L;
106   private long _clientWriteTimeout = 60000L;
107   private long _clientConnectTimeout = 5000L;
108
109   private BuilderProgramContainer _serverProgram
110     = new BuilderProgramContainer();
111
112   private Server _server;
113
114   private volatile boolean _isClosed;
115
116   public Cluster(Resin resin)
117   {
118     this();
119
120     _resin = resin;
121   }
122     
123   public Cluster()
124   {
125     _classLoader = new EnvironmentClassLoader();
126     _classLoader.setId("cluster:??");
127
128     _clusterLocal.set(this, _classLoader);
129   
130     Environment.addEnvironmentListener(this, _classLoader);
131     
132     Config.setCurrentVar("cluster", new Var());
133
134     _rootDirectory = Vfs.getPwd();
135   }
136
137   /**
138    * Returns the currently active local cluster.
139    */

140   public static Cluster getLocal()
141   {
142     Cluster cluster = _clusterLocal.get();
143
144     return cluster;
145   }
146
147   /**
148    * Returns the currently active local cluster.
149    */

150   public static Cluster getCluster(ClassLoader JavaDoc loader)
151   {
152     Cluster cluster = _clusterLocal.get(loader);
153
154     return cluster;
155   }
156
157   /**
158    * Sets the cluster id.
159    */

160   public void setId(String JavaDoc id)
161   {
162     if (id == null)
163       throw new NullPointerException JavaDoc();
164     
165     _id = id;
166
167     _classLoader.setId("cluster:" + _id);
168   }
169
170   /**
171    * Gets the cluster id.
172    */

173   public String JavaDoc getId()
174   {
175     return _id;
176   }
177
178   /**
179    * Returns the owning resin server.
180    */

181   public Resin getResin()
182   {
183     return _resin;
184   }
185
186   /**
187    * Returns the environment class loader.
188    */

189   public ClassLoader JavaDoc getClassLoader()
190   {
191     return _classLoader;
192   }
193
194   /**
195    * Returns the relax schema.
196    */

197   public String JavaDoc getSchema()
198   {
199     return "com/caucho/server/resin/cluster.rnc";
200   }
201
202   /**
203    * Gets the root directory.
204    */

205   public Path getRootDirectory()
206   {
207     return _rootDirectory;
208   }
209
210   /**
211    * Sets the root directory.
212    */

213   public void setRootDirectory(Path rootDirectory)
214   {
215     Vfs.setPwd(rootDirectory);
216     
217     _rootDirectory = rootDirectory;
218   }
219
220   /**
221    * Returns the admin.
222    */

223   public ClusterMXBean getAdmin()
224   {
225     return _admin;
226   }
227
228   /**
229    * Finds the first server with the given server-id.
230    */

231   public ClusterServer findServer(String JavaDoc id)
232   {
233     for (int i = _serverList.size() - 1; i >= 0; i--) {
234       ClusterServer server = _serverList.get(i);
235
236       if (server != null && server.getId().equals(id))
237         return server;
238     }
239
240     return null;
241   }
242
243   /**
244    * Adds a new server to the cluster.
245    */

246   public void addServerDefault(InitProgram program)
247     throws Throwable JavaDoc
248   {
249     _serverDefaultList.add(program);
250   }
251
252   /**
253    * Adds a new server to the cluster.
254    */

255   public ClusterServer createServer()
256     throws Throwable JavaDoc
257   {
258     ClusterServer server = new ClusterServer(this);
259
260     server.setIndex(_serverList.size());
261     
262     for (int i = 0; i < _serverDefaultList.size(); i++)
263       _serverDefaultList.get(i).configure(server);
264
265     return server;
266   }
267
268   /**
269    * Adds a new server to the cluster.
270    */

271   public void addServer(ClusterServer server)
272     throws ConfigException
273   {
274     ClusterServer oldServer = findServer(server.getId());
275
276     if (oldServer != null)
277       log.warning(L.l("duplicate <server> with id='{0}'",
278                       server.getId()));
279
280     _serverList.add(server);
281     _serverArray = new ClusterServer[_serverList.size()];
282     _serverList.toArray(_serverArray);
283
284     ClusterServer selfServer = getSelfServer();
285
286     if (selfServer == server)
287       Config.setCurrentVar("server", new ServerVar(server));
288   }
289
290   /**
291    * Adds a srun server.
292    */

293   public ClusterClient findClient(String JavaDoc address, int port)
294   {
295     for (int i = _serverList.size() - 1; i >= 0; i--) {
296       ClusterServer server = _serverList.get(i);
297       ClusterPort clusterPort = server.getClusterPort();
298
299       if (address.equals(clusterPort.getAddress()) &&
300       port == clusterPort.getPort()) {
301     // XXX:
302
//return server.getClient();
303
return null;
304       }
305     }
306
307     return null;
308   }
309
310   /**
311    * Returns the cluster store.
312    */

313   public StoreManager getStore()
314   {
315     return _clusterStore;
316   }
317
318   /**
319    * Sets the cluster store.
320    */

321   void setStore(StoreManager store)
322   {
323     _clusterStore = store;
324   }
325
326   /**
327    * Sets the max-idle time.
328    */

329   public void setClientMaxIdleTime(Period period)
330   {
331     _clientMaxIdleTime = period.getPeriod();
332   }
333
334   /**
335    * Gets the live time.
336    */

337   public long getClientMaxIdleTime()
338   {
339     return _clientMaxIdleTime;
340   }
341
342   /**
343    * Sets the live time.
344    *
345    * @deprecated
346    */

347   public void setClientLiveTime(Period period)
348   {
349     setClientMaxIdleTime(period);
350   }
351
352   /**
353    * Sets the client connection fail-recover time.
354    */

355   public void setClientFailRecoverTime(Period period)
356   {
357     _clientFailRecoverTime = period.getPeriod();
358   }
359
360   /**
361    * Gets the client fail-recover time.
362    */

363   public long getClientFailRecoverTime()
364   {
365     return _clientFailRecoverTime;
366   }
367
368   /**
369    * Sets the dead time.
370    *
371    * @deprecated
372    */

373   public void setClientDeadTime(Period period)
374   {
375     setClientFailRecoverTime(period);
376   }
377
378   /**
379    * Sets the client warmup time.
380    */

381   public void setClientWarmupTime(Period period)
382   {
383     _clientWarmupTime = period.getPeriod();
384   }
385
386   /**
387    * Gets the client warmup time.
388    */

389   public long getClientWarmupTime()
390   {
391     return _clientWarmupTime;
392   }
393
394   /**
395    * Sets the connect timeout.
396    */

397   public void setClientConnectTimeout(Period period)
398   {
399     _clientConnectTimeout = period.getPeriod();
400   }
401
402   /**
403    * Gets the connect timeout.
404    */

405   public long getClientConnectTimeout()
406   {
407     return _clientConnectTimeout;
408   }
409
410   /**
411    * Sets the read timeout.
412    */

413   public void setClientReadTimeout(Period period)
414   {
415     _clientReadTimeout = period.getPeriod();
416   }
417
418   /**
419    * Gets the read timeout.
420    */

421   public long getClientReadTimeout()
422   {
423     return _clientReadTimeout;
424   }
425
426   /**
427    * Sets the write timeout.
428    */

429   public void setClientWriteTimeout(Period period)
430   {
431   }
432
433   public StoreManager createJdbcStore()
434     throws ConfigException
435   {
436     if (getStore() != null)
437       throw new ConfigException(L.l("multiple jdbc stores are not allowed in a cluster."));
438
439     StoreManager store = null;
440
441     try {
442       Class JavaDoc cl = Class.forName("com.caucho.server.cluster.JdbcStore");
443
444       store = (StoreManager) cl.newInstance();
445
446       store.setCluster(this);
447
448       setStore(store);
449     } catch (Throwable JavaDoc e) {
450       log.log(Level.FINER, e.toString(), e);
451     }
452
453     if (store == null)
454       throw new ConfigException(L.l("'jdbc' persistent sessions are available in Resin Professional. See http://www.caucho.com for information and licensing."));
455
456     return store;
457   }
458
459   public StoreManager createPrivateFileStore()
460     throws ConfigException
461   {
462     StoreManager store = createFileStore();
463
464     setStore(null);
465
466     return store;
467   }
468
469   public StoreManager createFileStore()
470     throws ConfigException
471   {
472     if (getStore() != null)
473       throw new ConfigException(L.l("multiple file stores are not allowed in a cluster."));
474
475     StoreManager store = null;
476
477     try {
478       Class JavaDoc cl = Class.forName("com.caucho.server.cluster.FileStore");
479
480       store = (StoreManager) cl.newInstance();
481
482       store.setCluster(this);
483
484       setStore(store);
485     } catch (Throwable JavaDoc e) {
486       log.log(Level.FINER, e.toString(), e);
487     }
488
489     if (store == null)
490       throw new ConfigException(L.l("'file' persistent sessions are available in Resin Professional. See http://www.caucho.com for information and licensing."));
491
492     return store;
493   }
494
495   public StoreManager createClusterStore()
496     throws ConfigException
497   {
498     if (getStore() != null)
499       throw new ConfigException(L.l("multiple cluster stores are not allowed in a cluster."));
500
501     StoreManager store = null;
502
503     try {
504       Class JavaDoc cl = Class.forName("com.caucho.server.cluster.ClusterStore");
505
506       store = (StoreManager) cl.newInstance();
507
508       store.setCluster(this);
509
510       setStore(store);
511     } catch (Throwable JavaDoc e) {
512       log.log(Level.FINER, e.toString(), e);
513     }
514
515     if (store == null)
516       throw new ConfigException(L.l("'cluster' persistent sessions are available in Resin Professional. See http://www.caucho.com for information and licensing."));
517
518     return store;
519   }
520
521   /**
522    * Adds a program.
523    */

524   public void addBuilderProgram(BuilderProgram program)
525   {
526     _serverProgram.addProgram(program);
527   }
528
529   /**
530    * Initializes the cluster.
531    */

532   @PostConstruct
533   public void init()
534     throws ConfigException
535   {
536     String JavaDoc serverId = _serverIdLocal.get();
537
538     if (serverId == null)
539       serverId = "";
540
541     ClusterServer self = findServer(serverId);
542
543     if (self != null)
544       _clusterLocal.set(this);
545     else if (_clusterLocal.get() == null && _serverList.size() == 0) {
546       // if it's the empty cluster, add it
547
_clusterLocal.set(this);
548     }
549
550     try {
551       String JavaDoc name = _id;
552
553       if (name == null)
554         name = "";
555
556       ObjectName JavaDoc objectName = Jmx.getObjectName("type=Cluster,name=" + name);
557
558       _admin = new ClusterAdmin(this);
559
560       Jmx.register(_admin, objectName);
561
562       _objectName = objectName;
563     } catch (Throwable JavaDoc e) {
564       log.log(Level.FINER, e.toString(), e);
565     }
566   }
567
568   /**
569    * Returns the server id.
570    */

571   public static String JavaDoc getServerId()
572   {
573     return _serverIdLocal.get();
574   }
575
576   /**
577    * Returns the JMX object name.
578    */

579   public ObjectName JavaDoc getObjectName()
580   {
581     return _objectName == null ? null : _objectName;
582   }
583
584   /**
585    * Returns the server corresponding to the current server-id.
586    */

587   public ClusterServer getSelfServer()
588   {
589     _serverId = _serverIdLocal.get();
590
591     return getServer(_serverId);
592   }
593
594   /**
595    * Returns the server list.
596    */

597   public ClusterServer []getServerList()
598   {
599     return _serverArray;
600   }
601
602   /**
603    * Returns the server in the cluster with the given server-id.
604    */

605   public ClusterServer getServer(String JavaDoc serverId)
606   {
607     for (int i = 0; i < _serverList.size(); i++) {
608       ClusterServer server = _serverList.get(i);
609
610       if (server != null && server.getId().equals(serverId))
611         return server;
612     }
613
614     return null;
615   }
616
617   /**
618    * Returns the server with the matching index.
619    */

620   public ClusterServer getServer(int index)
621   {
622     for (int i = 0; i < _serverList.size(); i++) {
623       ClusterServer server = _serverList.get(i);
624
625       if (server != null && server.getIndex() == index)
626         return server;
627     }
628
629     return null;
630   }
631
632   /**
633    * Returns the matching ports.
634    */

635   public ArrayList JavaDoc<ClusterPort> getServerPorts(String JavaDoc serverId)
636   {
637     ArrayList JavaDoc<ClusterPort> ports = new ArrayList JavaDoc<ClusterPort>();
638
639     for (int i = 0; i < _serverList.size(); i++) {
640       ClusterServer server = _serverList.get(i);
641
642       if (server != null) {
643         ClusterPort port = server.getClusterPort();
644
645         if (port.getServerId().equals(serverId))
646           ports.add(port);
647       }
648     }
649
650     return ports;
651   }
652
653   /**
654    * Starts the server.
655    */

656   Server startServer(ClusterServer clusterServer)
657     throws Throwable JavaDoc
658   {
659     synchronized (this) {
660       if (_server != null)
661     return _server;
662
663       Server server = new Server(clusterServer);
664
665       _serverProgram.configure(server);
666
667       server.start();
668
669       _server = server;
670
671       return server;
672     }
673   }
674
675   /**
676    * Handles the case where a class loader has completed initialization
677    */

678   public void classLoaderInit(DynamicClassLoader loader)
679   {
680   }
681
682   /**
683    * Handles the case where a class loader is dropped.
684    */

685   public void classLoaderDestroy(DynamicClassLoader loader)
686   {
687   }
688
689   /**
690    * Handles the case where the environment is starting (after init).
691    */

692   public void environmentStart(EnvironmentClassLoader loader)
693   {
694     try {
695       if (_clusterStore != null)
696         _clusterStore.start();
697     } catch (Throwable JavaDoc e) {
698       log.log(Level.WARNING, e.toString(), e);
699     }
700   }
701
702   /**
703    * Handles the case where the environment is stopping
704    */

705   public void environmentStop(EnvironmentClassLoader loader)
706   {
707     try {
708       close();
709     } catch (Throwable JavaDoc e) {
710       log.log(Level.WARNING, e.toString(), e);
711     }
712   }
713
714   /**
715    * Closes the cluster.
716    */

717   public void close()
718   {
719     synchronized (this) {
720       if (_isClosed)
721         return;
722
723       _isClosed = true;
724     }
725
726     for (int i = 0; i < _serverList.size(); i++) {
727       ClusterServer server = _serverList.get(i);
728
729       try {
730         if (server != null)
731           server.close();
732       } catch (Throwable JavaDoc e) {
733         log.log(Level.WARNING, e.toString(), e);
734       }
735     }
736   }
737
738   public String JavaDoc toString()
739   {
740     return "Cluster[" + _id + "]";
741   }
742
743   /**
744    * EL variables
745    */

746   public class Var {
747     /**
748      * Returns the resin.id
749      */

750     public String JavaDoc getId()
751     {
752       return _id;
753     }
754
755     /**
756      * Returns the root directory.
757      *
758      * @return root directory
759      */

760     public Path getRoot()
761     {
762       return Cluster.this.getRootDirectory();
763     }
764
765     /**
766      * Returns the root directory.
767      *
768      * @return root directory
769      */

770     public Path getRootDir()
771     {
772       return getRoot();
773     }
774
775     /**
776      * Returns the root directory.
777      *
778      * @return root directory
779      */

780     public Path getRootDirectory()
781     {
782       return getRoot();
783     }
784   }
785
786   public class ServerVar {
787     private final ClusterServer _server;
788
789     public ServerVar(ClusterServer server)
790     {
791       _server = server;
792     }
793
794     public String JavaDoc getId()
795     {
796       return _server.getId();
797     }
798
799     private int getPort(Port port)
800     {
801       if (port == null)
802         return 0;
803
804       return port.getPort();
805     }
806
807     private String JavaDoc getAddress(Port port)
808     {
809       if (port == null)
810         return null;
811
812       String JavaDoc address = port.getAddress();
813
814       if (address == null || address.length() == 0)
815         address = "INADDR_ANY";
816
817       return address;
818     }
819
820     private Port getFirstPort(String JavaDoc protocol, boolean isSSL)
821     {
822       if (_server.getPorts() == null)
823         return null;
824
825       for (Port port : _server.getPorts()) {
826         if (protocol.equals(port.getProtocolName()) && (port.isSSL() == isSSL))
827           return port;
828       }
829
830       return null;
831     }
832
833     public String JavaDoc getAddress()
834     {
835       return getAddress(_server.getClusterPort());
836     }
837
838     public int getPort()
839     {
840       return getPort(_server.getClusterPort());
841     }
842
843     public String JavaDoc getHttpAddress()
844     {
845       return getAddress(getFirstPort("http", false));
846     }
847
848     public int getHttpPort()
849     {
850       return getPort(getFirstPort("http", false));
851     }
852
853
854     public String JavaDoc getHttpsAddress()
855     {
856       return getAddress(getFirstPort("http", true));
857     }
858
859     public int getHttpsPort()
860     {
861       return getPort(getFirstPort("http", true));
862     }
863
864     /**
865      * @deprecated backwards compat.
866      */

867     public Path getRoot()
868     {
869       Resin resin = Resin.getLocal();
870
871       return resin == null ? Vfs.getPwd() : resin.getRootDirectory();
872     }
873   }
874 }
875
Popular Tags