KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > monitor > services > MemoryMonitor


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.monitor.services;
23
24 import org.jboss.system.ServiceMBeanSupport;
25 import org.jboss.util.Strings;
26
27 import javax.management.ObjectName JavaDoc;
28 import javax.management.Notification JavaDoc;
29
30 import org.jboss.monitor.alarm.Alarm;
31 import org.jboss.monitor.alarm.AlarmManager;
32 import org.jboss.monitor.alarm.MBeanImplAccess;
33
34 /**
35  * MemoryMonitor class.
36  *
37  * @jmx:mbean
38  * extends="org.jboss.system.ServiceMBean"
39  *
40  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
41  * @version $Revision: 37459 $
42  */

43 public class MemoryMonitor extends ServiceMBeanSupport
44    implements MemoryMonitorMBean
45 {
46    // Constants -----------------------------------------------------
47

48    /** Notification type which indicates a memory low alarm */
49    public static final String JavaDoc MEMORY_LOW = "jboss.alarm.memory.low";
50    
51    /** Free memory key to use in AlarmNotification/userData map */
52    public static final String JavaDoc FREE_MEMORY_KEY = "freeMemory";
53    
54    /** default warning threshold */
55    public static final String JavaDoc DEFAULT_WARNING_THRESHOLD = "5m";
56    
57    /** default number of measurements to trigger warning */
58    public static final int DEFAULT_WARNING_MEASUREMENTS = 3;
59    
60    /** default critical threshold */
61    public static final String JavaDoc DEFAULT_CRITICAL_THRESHOLD = "2m";
62    
63    /** default sampling period */
64    public static final String JavaDoc DEFAULT_SAMPLING_PERIOD = "5sec";
65    
66    /** conversion constants */
67    public static final long KILO = 1024;
68    public static final long MEGA = 1024 * 1024;
69    public static final long GIGA = 1024 * 1024 * 1024;
70    
71    // Private -------------------------------------------------------
72

73    /** warning threshold */
74    private long wThreshold;
75    
76    /** warning threshold stringfied */
77    private String JavaDoc wThresholdString;
78
79    /** number of measurements in the warning area before warning is sent */
80    private int wMeasurements;
81    
82    /** critical threshold */
83    private long cThreshold;
84    
85    /** critical threshold stringfied */
86    private String JavaDoc cThresholdString;
87    
88    /** memory sampling period */
89    private long samplingPeriod;
90    
91    /** sampling period stringfied */
92    private String JavaDoc samplingPeriodString;
93    
94    /** control sampling thread */
95    private boolean isStopRequested;
96    
97    /** last measurement of free memory */
98    private long freeMemory;
99    
100    /** number of samples in the warning area */
101    private int warningSamples;
102    
103    /** alarm manager */
104    AlarmManager alm =
105       new AlarmManager(
106          new MBeanImplAccess() {
107             public ObjectName JavaDoc getMBeanName() { return getServiceName(); }
108             public long getSequenceNumber() { return getNextNotificationSequenceNumber(); }
109             public void emitNotification(Notification JavaDoc n) { sendNotification(n); }
110       });
111    
112    // Constructors --------------------------------------------------
113

114    /**
115     * CTOR
116     */

117    public MemoryMonitor()
118    {
119       // setup default values
120
setFreeMemoryWarningThreshold(DEFAULT_WARNING_THRESHOLD);
121       setFreeMemoryCriticalThreshold(DEFAULT_CRITICAL_THRESHOLD);
122       setSamplingPeriod(DEFAULT_SAMPLING_PERIOD);
123       this.wMeasurements = DEFAULT_WARNING_MEASUREMENTS;
124    }
125                 
126    // Attributes --------------------------------------------------
127

128    /**
129     * @jmx:managed-attribute
130     */

131    public void setTriggeringWarningMeasurements(int measurements)
132    {
133       if (measurements > 0)
134       {
135          this.wMeasurements = measurements;
136       }
137    }
138
139    /**
140     * @jmx:managed-attribute
141     */

142    public int getTriggeringWarningMeasurements()
143    {
144       return this.wMeasurements;
145    }
146    
147    /**
148     * @jmx:managed-attribute
149     */

150    public void setFreeMemoryWarningThreshold(String JavaDoc s)
151    {
152       synchronized (this)
153       {
154          this.wThreshold = parseMemorySpec(s);
155          this.wThresholdString = s;
156       }
157    }
158
159    /**
160     * @jmx:managed-attribute
161     */

162    public String JavaDoc getFreeMemoryWarningThreshold()
163    {
164       return this.wThresholdString;
165    }
166    
167    /**
168     * @jmx:managed-attribute
169     */

170    public void setFreeMemoryCriticalThreshold(String JavaDoc s)
171    {
172       synchronized (this)
173       {
174          this.cThreshold = parseMemorySpec(s);
175          this.cThresholdString = s;
176       }
177    }
178    
179    /**
180     * @jmx:managed-attribute
181     */

182    public String JavaDoc getFreeMemoryCriticalThreshold()
183    {
184       return this.cThresholdString;
185    }
186
187    /**
188     * @jmx:managed-attribute
189     */

190    public void setSamplingPeriod(String JavaDoc s)
191    {
192       synchronized (this)
193       {
194          this.samplingPeriod = Strings.parsePositiveTimePeriod(s);
195          this.samplingPeriodString = s;
196       }
197    }
198    
199    /**
200     * @jmx:managed-attribute
201     */

202    public String JavaDoc getSamplingPeriod()
203    {
204       return this.samplingPeriodString;
205    }
206
207    /**
208     * @jmx:managed-attribute
209     */

210    public long getFreeMemorySample()
211    {
212       synchronized (this)
213       {
214          return this.freeMemory;
215       }
216    }
217
218    /**
219     * @jmx:managed-attribute
220     */

221    public String JavaDoc getSeverity()
222    {
223       return alm.getSeverityAsString(MEMORY_LOW);
224    }
225    
226    // Service Lifecycle ---------------------------------------------
227

228    public void startService() throws Exception JavaDoc
229    {
230       // Annonymous class
231
Runnable JavaDoc r = new Runnable JavaDoc()
232       {
233          public void run()
234          {
235             log.debug("Started memory monitor thread" +
236                      ", samplingPeriod=" + MemoryMonitor.this.samplingPeriodString +
237                      ", warningThreshold=" + MemoryMonitor.this.wThresholdString +
238                      ", criticalThreshold=" + MemoryMonitor.this.cThresholdString);
239
240             // make copies of config params
241
long wThreshold;
242             long cThreshold;
243             long samplingPeriod;
244             
245             synchronized(MemoryMonitor.this)
246             {
247                wThreshold = MemoryMonitor.this.wThreshold;
248                cThreshold = MemoryMonitor.this.cThreshold;
249                samplingPeriod = MemoryMonitor.this.samplingPeriod;
250             }
251             
252             // initialise warningSamples countdown
253
warningSamples = wMeasurements;
254             
255             while (!isStopRequested)
256             {
257                sampleMemory(wThreshold, cThreshold);
258          
259                if (!isStopRequested)
260                {
261                   try
262                   {
263                      Thread.sleep(samplingPeriod);
264                   }
265                   catch (InterruptedException JavaDoc e)
266                   {
267                      // ignored
268
}
269                }
270             }
271             log.debug("Stopped memory monitor thread");
272          }
273       };
274       
275       // check for validity
276
if (this.cThreshold > this.wThreshold)
277       {
278          throw new Exception JavaDoc(
279             "FreeMemoryWarningThreshold (" + this.wThreshold +
280             ") set lower than FreeMemoryCriticalThreshold (" + this.cThreshold + ")");
281       }
282       isStopRequested = false;
283       Thread JavaDoc t = new Thread JavaDoc(r, "Memory monitor thread of \"" + getServiceName() + "\"");
284       t.start();
285    }
286    
287    public void stopService()
288    {
289       // signal thread to stop
290
this.isStopRequested = true;
291    }
292    
293    // Private Methods -----------------------------------------------
294

295    /**
296     * The real stuff
297     */

298    private void sampleMemory(long wThreshold, long cThreshold)
299    {
300       long freeMemory = Runtime.getRuntime().freeMemory();
301       
302       synchronized (this)
303       {
304          this.freeMemory = freeMemory;
305       };
306       
307       if (freeMemory <= cThreshold)
308       { // critical
309
alm.setAlarm(
310             MEMORY_LOW,
311             Alarm.SEVERITY_CRITICAL,
312             "Free memory in critical state",
313             FREE_MEMORY_KEY,
314             new Long JavaDoc(freeMemory)
315          );
316          // reset warning countdown
317
warningSamples = wMeasurements;
318       }
319       else if (freeMemory <= wThreshold)
320       {
321          if (warningSamples > 0)
322          {
323             --warningSamples;
324          }
325          if (warningSamples == 0
326             || alm.getSeverity(MEMORY_LOW) == Alarm.SEVERITY_CRITICAL)
327          {
328             alm.setAlarm(
329                MEMORY_LOW,
330                Alarm.SEVERITY_WARNING,
331                "Free memory getting low",
332                FREE_MEMORY_KEY,
333                new Long JavaDoc(freeMemory)
334             );
335          }
336       }
337       else
338       {
339          alm.setAlarm(
340             MEMORY_LOW,
341             Alarm.SEVERITY_NORMAL,
342             "Free memory at normal levels",
343             FREE_MEMORY_KEY,
344             new Long JavaDoc(freeMemory)
345          );
346          // reset warning countdown
347
warningSamples = wMeasurements;
348       }
349    }
350    
351    /**
352     * Parses a memory specification into a long.
353     *
354     * Translates the [kK|mM|gG] suffixes
355     *
356     * For example:
357     * "10" -> 10 (bytes)
358     * "10k" -> 10240 (bytes)
359     * "10m" -> 10485760 (bytes)
360     * "10g" -> 10737418240 (bytes)
361     */

362    private static long parseMemorySpec(String JavaDoc s)
363    {
364       try
365       {
366          int len = s.length();
367          long factor = 0;
368          
369          switch (s.charAt(len - 1))
370          {
371             case 'k':
372             case 'K':
373                factor = KILO;
374                s = s.substring(0, len - 1);
375                break;
376                
377             case 'm':
378             case 'M':
379                factor = MEGA;
380                s = s.substring(0, len - 1);
381                break;
382                
383             case 'g':
384             case 'G':
385                factor = GIGA;
386                s = s.substring(0, len - 1);
387                break;
388             
389             default:
390                factor = 1;
391                break;
392          }
393          long retval = Long.parseLong(s) * factor;
394          
395          if (retval < 0)
396          {
397             throw new NumberFormatException JavaDoc();
398          }
399          return retval;
400       }
401       catch (RuntimeException JavaDoc e)
402       {
403          throw new NumberFormatException JavaDoc("Not a valid memory specification: " + s);
404       }
405    }
406    
407 }
408
Popular Tags