001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2006 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: JkCluster.java 9435 2006-08-21 12:36:07Z danesa $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.management.cluster;
025:
026: import java.util.ArrayList;
027: import java.util.Iterator;
028: import java.util.StringTokenizer;
029:
030: import javax.management.JMException;
031: import javax.management.MBeanServer;
032: import javax.management.ObjectName;
033:
034: import org.objectweb.jonas.common.JProp;
035: import org.objectweb.jonas.jmx.JonasObjectName;
036: import org.objectweb.jonas.management.monitoring.ServerProxy;
037:
038: import org.objectweb.util.monolog.api.BasicLevel;
039:
040: /**
041: * JkCluster are used for Web level load balancing
042: * @author Adriana Danes
043: * @author Philippe Durieux
044: */
045: public class JkCluster extends BaseCluster implements JkClusterMBean {
046:
047: /**
048: * The type of Cluster, that is part of the MBean ObjectName
049: */
050: private String type = "JkCluster";
051:
052: /**
053: * This properties are listed in "worker.properties" config file.
054: */
055: private JProp jprop = null;
056:
057: /**
058: * The Load Balancer Worker.
059: * Its name is given to the Cluster.
060: */
061: private String lbWorker = null;
062:
063: /**
064: * These servers are actually the jonas servers that compose the Cluster.
065: * Built from "workers.properties".
066: */
067: private ArrayList balancedWorkers = new ArrayList();
068:
069: /**
070: * Web level loadbalancing cluster constructor
071: * Lookup for configuration file in JONAS_BASE/conf
072: * This is the "workers.properties" file from TOMCAT.
073: * @param cf ClusterFactory
074: * @throws JMException could not create MBean instance
075: */
076: public JkCluster(JkClusterFactory cf) throws JMException {
077: super (cf);
078:
079: // Read the "Worker.properties" configuration file.
080: try {
081: jprop = JProp.getInstance("workers.properties");
082: } catch (RuntimeException e) {
083: logger.log(BasicLevel.DEBUG,
084: "Cannot find workers.properties:" + e);
085: throw e;
086: }
087:
088: // Get the lbWorker defined in the config file.
089: getLbWorker();
090: if (lbWorker == null) {
091: logger.log(BasicLevel.WARN,
092: "No Load Balancer worker in workers.properties");
093: return;
094: }
095:
096: // Read the list of Workers defined in the workers.properties file
097: getBalancedWorkerList();
098:
099: // Give a name to the Cluster and register it as a MBean
100: setName(lbWorker);
101: cf.getMBeanServer().registerMBean(this , objectName);
102: }
103:
104: public ClusterMember createClusterMember(String svname,
105: ServerProxy proxy) {
106: return new JkClusterMember(svname, proxy);
107: }
108:
109: // --------------------------------------------------------------------------
110: // Other public methods
111: // --------------------------------------------------------------------------
112:
113: /**
114: * @return The String type to be put in the ObjectName
115: */
116: public String getType() {
117: return type;
118: }
119:
120: /**
121: * Add a Worker to the list of the JkCluster
122: * It should be known in workers.properties
123: * Make link between the member and the ServerProxy.
124: * @param workerName the worker name
125: * @param workerPort the worker port
126: * @param proxy The ServerProxy related object.
127: * @return True if correctly added in the List.
128: */
129: public boolean addWorker(String workerName, int workerPort,
130: ServerProxy proxy) {
131:
132: // Check if a the detected worker corresponds to a worker
133: // defined in the configuration file
134: // If not print a Warning and exit.
135: boolean found = false;
136: for (Iterator it = balancedWorkers.iterator(); it.hasNext();) {
137: String aWorkerName = (String) it.next();
138: if (workerName.equals(aWorkerName)) {
139: found = true;
140: // it corresponds to a defined worker if the port value
141: // is also corresponding
142: String portString = (String) getWorkerProp(workerName,
143: "port");
144: Integer portValue = new Integer(portString);
145: if (portValue != null
146: && portValue.intValue() != workerPort) {
147: logger.log(BasicLevel.WARN, "Bad port number for: "
148: + workerName);
149: }
150: break;
151: }
152: }
153: if (!found) {
154: logger.log(BasicLevel.WARN,
155: "Cannot find this worker in workers.properties:"
156: + workerName);
157: return false;
158: }
159:
160: // Create the JkClusterMember object (= a worker)
161: JkClusterMember worker = new JkClusterMember(workerName, proxy);
162: worker.setPort(workerPort);
163:
164: // Set configuration parameters (from workers.properties)
165: String host = (String) getWorkerProp(workerName, "host");
166: if (host != null) {
167: worker.setHost(host);
168: }
169: String type = (String) getWorkerProp(workerName, "type");
170: if (type != null) {
171: worker.setType(type);
172: }
173: String lbFactorString = (String) getWorkerProp(workerName,
174: "lbfactor");
175: Integer lbFactor = new Integer(lbFactorString);
176: if (lbFactor != null) {
177: worker.setLbfactor(lbFactor.intValue());
178: }
179:
180: // Add this member if not already there
181: boolean added = addMember(worker);
182: if (added) {
183: // Build the ObjectName and register MBean
184: try {
185: ObjectName on = JonasObjectName.clusterMember(
186: workerName, getType(), name);
187: worker.setObjectName(on);
188: MBeanServer mbeanServer = jmx.getJmxServer();
189: if (mbeanServer.isRegistered(on)) {
190: mbeanServer.unregisterMBean(on);
191: }
192: mbeanServer.registerMBean(worker, on);
193: } catch (JMException e) {
194: logger.log(BasicLevel.WARN, "Cannot register Worker "
195: + workerName + ": " + e);
196: }
197: }
198: return added;
199: }
200:
201: // --------------------------------------------------------------------------
202: // private methods
203: // --------------------------------------------------------------------------
204:
205: /**
206: * Get the loadbalancer worker defined in worker.properties.
207: * Found by its type that is equals to "lb"
208: */
209: private void getLbWorker() {
210: // Get the worker list in order to find the balancer worker
211: String valueList = (String) jprop.getValue("worker.list");
212: StringTokenizer st = new StringTokenizer(valueList, ",");
213: while (st.hasMoreTokens()) {
214: String aWorker = (String) st.nextToken();
215: // check if this is a load balancer worker
216: String key = "worker." + aWorker + ".type";
217: String type = (String) jprop.getValue(key);
218: if ("lb".equals(type)) {
219: lbWorker = aWorker;
220: break;
221: }
222: }
223: }
224:
225: /**
226: * Get the balance worker list defined in worker.properties
227: * into balancedWorkers attribute.
228: */
229: private void getBalancedWorkerList() {
230: // Get the balanced workers
231: String key = "worker." + lbWorker + ".balanced_workers";
232: String valueList = (String) jprop.getValue(key);
233: StringTokenizer st = new StringTokenizer(valueList, ",");
234: while (st.hasMoreTokens()) {
235: String aWorker = (String) st.nextToken();
236: // Sanity check: control the type.
237: key = "worker." + aWorker + ".type";
238: String type = (String) jprop.getValue(key);
239: if ("ajp13".equals(type)) {
240: balancedWorkers.add(aWorker);
241: } else {
242: logger.log(BasicLevel.WARN, "Bad worker type: " + type);
243: }
244: }
245: }
246:
247: /**
248: * Get a worker directive value
249: * @param workerName the worker name
250: * @param directive the worker directive
251: * @return the worker directive value
252: */
253: private Object getWorkerProp(String workerName, String directive) {
254: Object valueObj = null;
255: String key = "worker." + workerName + "." + directive;
256: if (jprop != null) {
257: valueObj = jprop.getValue(key);
258: }
259: return valueObj;
260: }
261:
262: // ----- Management methods ----
263: /**
264: * @return The list of the load balancer workers' name
265: */
266: public String[] getBalancedWorkers() {
267: String[] result = new String[balancedWorkers.size()];
268: for (int i = 0; i < result.length; i++) {
269: result[i] = (String) balancedWorkers.get(i);
270: }
271: return result;
272: }
273:
274: /**
275: * @return true if stcky session
276: */
277: public boolean isStickySession() {
278: String key = "worker." + lbWorker + ".sticky_session";
279: return new Boolean((String) jprop.getValue(key)).booleanValue();
280: }
281:
282: }
|