KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > loadbalancer > scheduler > AbstractScheduler


1 /*
2  * JBoss, the OpenSource WebOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.web.loadbalancer.scheduler;
8
9 import java.net.MalformedURLException JavaDoc;
10 import java.net.URL JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import javax.management.MBeanServer JavaDoc;
14 import javax.management.Notification JavaDoc;
15 import javax.management.NotificationFilter JavaDoc;
16 import javax.management.NotificationListener JavaDoc;
17 import javax.management.ObjectName JavaDoc;
18 import javax.servlet.http.Cookie JavaDoc;
19
20 import org.jboss.mx.util.MBeanServerLocator;
21 import org.jboss.util.xml.XmlHelper;
22 import org.jboss.web.loadbalancer.util.Constants;
23 import org.jboss.web.loadbalancer.util.Request;
24 import org.w3c.dom.Element JavaDoc;
25 import org.jboss.system.*;
26
27 /**
28  * Base-class for Scheduler
29  *
30  * @jmx:mbean name="jboss.web.loadbalancer: service=Scheduler"
31  * extends="org.jboss.system.ServiceMBean, org.jboss.web.loadbalancer.scheduler.SchedulerMBean"
32  *
33  * @author Thomas Peuss <jboss@peuss.de>
34  * @version $Revision: 1.6 $
35  */

36 public abstract class AbstractScheduler
37     extends ServiceMBeanSupport
38     implements AbstractSchedulerMBean, NotificationListener JavaDoc
39 {
40   protected ArrayList JavaDoc hostsUp = new ArrayList JavaDoc();
41   protected ArrayList JavaDoc hostsDown = new ArrayList JavaDoc();
42   protected String JavaDoc stickyCookieName;
43   protected boolean useStickySession = false;
44   protected Element JavaDoc config;
45
46   /**
47    * Override this method to create a new scheduler.
48    * @return
49    */

50   protected abstract Host getNextHost();
51
52   protected void stopService() throws java.lang.Exception JavaDoc
53   {
54     // Register Hosts as MBeans
55
deregisterHostMBeans();
56   }
57
58   /**
59    * @jmx:managed-attribute
60    * @param config
61    */

62   public void setConfig(Element JavaDoc config)
63   {
64     this.config = config;
65   }
66
67   protected void createService() throws java.lang.Exception JavaDoc
68   {
69     // Add all hosts to the host-up-list
70
addHostsFromConfig(config);
71
72     // do we use sticky session?
73
if (XmlHelper.getUniqueChildContent(config, "sticky-session").
74         equalsIgnoreCase("true"))
75     {
76       useStickySession = true;
77       stickyCookieName = XmlHelper.getUniqueChildContent(config,
78           "sticky-session-cookie-name");
79     }
80
81     if (log.isDebugEnabled())
82     {
83       if (useStickySession)
84       {
85         log.debug("Using sticky sessions with Cookie name=" + stickyCookieName);
86       }
87       else
88       {
89         log.debug("Using NO sticky sessions");
90       }
91     }
92   }
93
94   protected synchronized void addHostsFromConfig(Element JavaDoc config) throws
95       Exception JavaDoc
96   {
97     Iterator JavaDoc hostIterator = XmlHelper.getChildrenByTagName(XmlHelper.
98         getUniqueChild(config, "hosts"), "host");
99
100     while (hostIterator.hasNext())
101     {
102       Element JavaDoc hostElement = (Element JavaDoc) hostIterator.next();
103       String JavaDoc hostUrl = XmlHelper.getUniqueChildContent(hostElement, "host-url");
104
105       // if the host has no trailing slash we add one
106
if (!hostUrl.endsWith("/"))
107       {
108         hostUrl += "/";
109       }
110
111       Host host = addHost(hostUrl);
112
113       try
114       {
115         host.setLbFactor(Integer.parseInt(XmlHelper.getUniqueChildContent(
116             hostElement, "lb-factor")));
117       }
118       catch (Exception JavaDoc e)
119       {
120         log.debug("Could read LbFactor for Host " + host.getUrl() +
121                  " - assuming LbFactor 1");
122         host.setLbFactor(1);
123       }
124     }
125   }
126
127   protected ObjectName JavaDoc genObjectNameForHost(Host host) throws Exception JavaDoc
128   {
129     return new ObjectName JavaDoc("jboss.web.loadbalancer: type=Node, protocol=" +
130                           host.getUrl().getProtocol() + ", host=" +
131                           host.getUrl().getHost() + ", port=" +
132                           (host.getUrl().getPort() == -1 ?
133                           host.getUrl().getDefaultPort() :
134                           host.getUrl().getPort()));
135   }
136
137   protected void registerHostMBean(Host host)
138   {
139     MBeanServer JavaDoc mbs = MBeanServerLocator.locateJBoss();
140     try
141     {
142       mbs.registerMBean(host, genObjectNameForHost(host));
143       host.addNotificationListener(this,
144                                    new NotificationFilter JavaDoc()
145       {
146         public boolean isNotificationEnabled(Notification JavaDoc notification)
147         {
148           return (notification instanceof HostStateChangedNotification);
149         }
150       }
151
152       , host);
153     }
154     catch (Exception JavaDoc ex)
155     {
156       log.error("Could not register HostMBean", ex);
157     }
158   }
159
160   protected void deregisterHostMBean(Host host)
161   {
162     MBeanServer JavaDoc mbs = MBeanServerLocator.locateJBoss();
163     try
164     {
165       mbs.unregisterMBean(genObjectNameForHost(host));
166       host.removeNotificationListener(this);
167     }
168     catch (Exception JavaDoc ex)
169     {
170       log.error("Could not unregister HostMBean", ex);
171     }
172   }
173
174   protected synchronized void deregisterHostMBeans() throws Exception JavaDoc
175   {
176     Iterator JavaDoc hostIterator = hostsUp.iterator();
177
178     while (hostIterator.hasNext())
179     {
180       Host host = (Host) hostIterator.next();
181       deregisterHostMBean(host);
182     }
183
184     hostIterator = hostsDown.iterator();
185     while (hostIterator.hasNext())
186     {
187       Host host = (Host) hostIterator.next();
188       deregisterHostMBean(host);
189     }
190   }
191
192   public void getHost(Request schedRequest) throws
193       NoHostAvailableException
194   {
195     Host host = null;
196
197     // first look if we can find the sticky host for this request
198
host = findStickyHost(schedRequest);
199
200     // not found -> find a host for this request
201
while (host == null)
202     {
203       if (hostsUp.size() == 0)
204       {
205         throw new NoHostAvailableException("No host to schedule request");
206       }
207       host = getNextHost();
208     }
209
210     schedRequest.setHost(host);
211
212     // if we use sticky session -> set the cookie
213
if (useStickySession)
214     {
215       setStickyCookie(schedRequest);
216     }
217   }
218
219   /**
220    * Set the sticky session cookie.
221    */

222   protected void setStickyCookie(Request schedRequest)
223   {
224     Cookie JavaDoc cookie = new Cookie JavaDoc(stickyCookieName,
225                                Integer.toString(schedRequest.getHost().hashCode()));
226     cookie.setPath("/");
227     cookie.setMaxAge( -1);
228     schedRequest.getResponse().addCookie(cookie);
229   }
230
231   /**
232    * Find the sticky host for the given request
233    * @param request The request we want to find the sticky host for
234        * @return null=host not found, otherwise the sticky host URL for this request
235    */

236   protected Host findStickyHost(Request schedRequest)
237   {
238     Host host = null;
239     if (useStickySession)
240     {
241       Cookie JavaDoc[] cookies = schedRequest.getRequest().getCookies();
242
243       for (int i = 0; cookies != null && i < cookies.length; ++i)
244       {
245         Cookie JavaDoc cookie = cookies[i];
246
247         if (cookie.getName().equals(stickyCookieName))
248         {
249           log.debug("Sticky Cookie found!");
250           int cookieHash = Integer.parseInt(cookie.getValue());
251           Iterator JavaDoc iter = hostsUp.iterator();
252
253           while (iter.hasNext())
254           {
255             Host tempHost = (Host) iter.next();
256             if (tempHost.hashCode() == cookieHash)
257             {
258               host = tempHost;
259               if (log.isDebugEnabled())
260               {
261                 log.debug("Sticky Cookie sticks client to host with URL " +
262                           tempHost.toString());
263               }
264               break;
265             }
266           }
267           break;
268         }
269       }
270       return host;
271     }
272     else
273     {
274       return null;
275     }
276   }
277
278   protected synchronized void markNodeDown(Host host)
279   {
280     int index = hostsUp.indexOf(host);
281     if (index == -1)
282     {
283       return;
284     }
285     hostsUp.remove(index);
286     hostsDown.add(host);
287
288 // host.setState(Constants.STATE_NODE_DOWN);
289
}
290
291   protected synchronized void markNodeUp(Host host)
292   {
293     int index = hostsDown.indexOf(host);
294     if (index == -1)
295     {
296       return;
297     }
298     hostsDown.remove(index);
299     hostsUp.add(host);
300
301 // host.setState(Constants.STATE_NODE_UP);
302
}
303
304   // MBean Interface
305
/**
306    * Get the list of all hosts that have been marked down.
307    * @jmx:managed-attribute
308    */

309   public ArrayList JavaDoc getHostsDown()
310   {
311     return hostsDown;
312   }
313
314   /**
315    * Get the list of all hosts that have been marked up.
316    * @jmx:managed-attribute
317    */

318   public ArrayList JavaDoc getHostsUp()
319   {
320     return hostsUp;
321   }
322
323   /**
324    * Add a host to the up list.
325    * @jmx:managed-operation
326    */

327   public synchronized Host addHost(String JavaDoc hostString) throws
328       MalformedURLException JavaDoc
329   {
330     if (hostString == null)
331     {
332       return null;
333     }
334     if (!hostString.endsWith("/"))
335     {
336       hostString += "/";
337     }
338     Host host = new Host(new URL JavaDoc(hostString));
339
340     // Host already added?
341
if (hostsUp.indexOf(host) > -1 || hostsDown.indexOf(host) > -1)
342     {
343       log.info("Host " + hostString + " already there. Ignored");
344       return null;
345     }
346
347     hostsUp.add(host);
348     registerHostMBean(host);
349
350     return host;
351   }
352
353   /**
354    * Remove a host from the up list.
355    * @jmx:managed-operation
356    */

357   public synchronized void removeHost(URL JavaDoc url)
358   {
359     if (url == null)
360     {
361       return;
362     }
363     Host host = new Host(url);
364
365     int index = hostsUp.indexOf(host);
366     if (index > -1)
367     {
368       deregisterHostMBean( (Host) hostsUp.get(index));
369       hostsUp.remove(index);
370     }
371
372     index = hostsDown.indexOf(host);
373     if (index > -1)
374     {
375       deregisterHostMBean( (Host) hostsDown.get(index));
376       hostsDown.remove(index);
377     }
378   }
379
380   public void handleNotification(Notification JavaDoc notification, Object JavaDoc handback)
381   {
382     HostStateChangedNotification hscn=(HostStateChangedNotification)notification;
383
384     Host host=(Host)hscn.getSource();
385
386     switch (host.getState())
387     {
388       case Constants.STATE_NODE_UP:
389         markNodeUp(host);
390         break;
391       case Constants.STATE_NODE_DOWN:
392       case Constants.STATE_NODE_FORCED_DOWN:
393         markNodeDown(host);
394       break;
395     }
396   }
397 }
398
Popular Tags