KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > monitor > CmsMemoryMonitor


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/monitor/CmsMemoryMonitor.java,v $
3  * Date : $Date: 2006/03/27 14:53:04 $
4  * Version: $Revision: 1.58 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.monitor;
33
34 import org.opencms.cache.CmsLruCache;
35 import org.opencms.file.CmsFile;
36 import org.opencms.file.CmsGroup;
37 import org.opencms.file.CmsObject;
38 import org.opencms.file.CmsProject;
39 import org.opencms.file.CmsProperty;
40 import org.opencms.file.CmsPropertyDefinition;
41 import org.opencms.file.CmsResource;
42 import org.opencms.file.CmsUser;
43 import org.opencms.flex.CmsFlexCache.CmsFlexCacheVariation;
44 import org.opencms.mail.CmsMailTransport;
45 import org.opencms.mail.CmsSimpleMail;
46 import org.opencms.main.CmsEvent;
47 import org.opencms.main.CmsLog;
48 import org.opencms.main.CmsSessionManager;
49 import org.opencms.main.I_CmsEventListener;
50 import org.opencms.main.OpenCms;
51 import org.opencms.scheduler.I_CmsScheduledJob;
52 import org.opencms.security.CmsAccessControlList;
53 import org.opencms.security.CmsPermissionSet;
54 import org.opencms.util.CmsDateUtil;
55 import org.opencms.util.CmsStringUtil;
56 import org.opencms.util.CmsUUID;
57 import org.opencms.util.PrintfFormat;
58
59 import java.util.ArrayList JavaDoc;
60 import java.util.Arrays JavaDoc;
61 import java.util.Collections JavaDoc;
62 import java.util.ConcurrentModificationException JavaDoc;
63 import java.util.Date JavaDoc;
64 import java.util.HashMap JavaDoc;
65 import java.util.Iterator JavaDoc;
66 import java.util.List JavaDoc;
67 import java.util.Map JavaDoc;
68
69 import javax.mail.internet.InternetAddress JavaDoc;
70
71 import org.apache.commons.collections.map.LRUMap;
72 import org.apache.commons.logging.Log;
73
74 /**
75  * Monitors OpenCms memory consumtion.<p>
76  *
77  * @author Carsten Weinholz
78  * @author Michael Emmerich
79  * @author Alexander Kandzior
80  *
81  * @version $Revision: 1.58 $
82  *
83  * @since 6.0.0
84  */

85 public class CmsMemoryMonitor implements I_CmsScheduledJob {
86
87     /** Set interval for clearing the caches to 10 minutes. */
88     private static final int INTERVAL_CLEAR = 1000 * 60 * 10;
89
90     /** The log object for this class. */
91     private static final Log LOG = CmsLog.getLog(CmsMemoryMonitor.class);
92
93     /** Flag indicating if monitor is currently running. */
94     private static boolean m_currentlyRunning;
95
96     /** Maximum depth for object size recursion. */
97     private static final int MAX_DEPTH = 5;
98
99     /** The memory monitor configuration. */
100     private CmsMemoryMonitorConfiguration m_configuration;
101
102     /** Interval in which emails are send. */
103     private int m_intervalEmail;
104
105     /** Interval in which the log is written. */
106     private int m_intervalLog;
107
108     /** Interval between 2 warnings. */
109     private int m_intervalWarning;
110
111     /** The time the caches were last cleared. */
112     private long m_lastClearCache;
113
114     /** The time the last status email was send. */
115     private long m_lastEmailStatus;
116
117     /** The time the last warning email was send. */
118     private long m_lastEmailWarning;
119
120     /** The time the last status log was written. */
121     private long m_lastLogStatus;
122
123     /** The time the last warning log was written. */
124     private long m_lastLogWarning;
125
126     /** The number of times the log entry was written. */
127     private int m_logCount;
128
129     /** Memory percentage to reach to go to warning level. */
130     private int m_maxUsagePercent;
131
132     /** The average memory status. */
133     private CmsMemoryStatus m_memoryAverage;
134
135     /** The current memory status. */
136     private CmsMemoryStatus m_memoryCurrent;
137
138     /** Contains the object to be monitored. */
139     private Map JavaDoc m_monitoredObjects;
140
141     /** Flag for memory warning mail send. */
142     private boolean m_warningLoggedSinceLastStatus;
143
144     /** Flag for memory warning mail send. */
145     private boolean m_warningSendSinceLastStatus;
146
147     /**
148      * Empty constructor, required by OpenCms scheduler.<p>
149      */

150     public CmsMemoryMonitor() {
151
152         m_monitoredObjects = new HashMap JavaDoc();
153     }
154
155     /**
156      * Returns the size of objects that are instances of
157      * <code>byte[]</code>, <code>String</code>, <code>CmsFile</code>,<code>I_CmsLruCacheObject</code>.<p>
158      * For other objects, a size of 0 is returned.
159      *
160      * @param obj the object
161      * @return the size of the object
162      */

163     public static int getMemorySize(Object JavaDoc obj) {
164
165         if (obj instanceof I_CmsMemoryMonitorable) {
166             return ((I_CmsMemoryMonitorable)obj).getMemorySize();
167         }
168
169         if (obj instanceof byte[]) {
170             // will always be a total of 16 + 8
171
return 8 + (int)(Math.ceil(((byte[])obj).length / 16.0) * 16.0);
172         }
173
174         if (obj instanceof String JavaDoc) {
175             // will always be a total of 16 + 24
176
return 24 + (int)(Math.ceil(((String JavaDoc)obj).length() / 8.0) * 16.0);
177         }
178
179         if (obj instanceof CmsFile) {
180             CmsFile f = (CmsFile)obj;
181             if (f.getContents() != null) {
182                 return f.getContents().length + 1024;
183             } else {
184                 return 1024;
185             }
186         }
187
188         if (obj instanceof CmsUUID) {
189             return 184; // worst case if UUID String has been generated
190
}
191
192         if (obj instanceof CmsPermissionSet) {
193             return 16; // two ints
194
}
195
196         if (obj instanceof CmsResource) {
197             return 1024; // estimated size
198
}
199
200         if (obj instanceof CmsUser) {
201             return 2048; // estimated size
202
}
203
204         if (obj instanceof CmsGroup) {
205             return 512; // estimated size
206
}
207
208         if (obj instanceof CmsProject) {
209             return 512;
210         }
211
212         if (obj instanceof Boolean JavaDoc) {
213             return 8; // one boolean
214
}
215
216         if (obj instanceof CmsProperty) {
217             int size = 8;
218
219             CmsProperty property = (CmsProperty)obj;
220             size += getMemorySize(property.getName());
221
222             if (property.getResourceValue() != null) {
223                 size += getMemorySize(property.getResourceValue());
224             }
225
226             if (property.getStructureValue() != null) {
227                 size += getMemorySize(property.getStructureValue());
228             }
229
230             return size;
231         }
232
233         if (obj instanceof CmsPropertyDefinition) {
234             int size = 8;
235
236             CmsPropertyDefinition propDef = (CmsPropertyDefinition)obj;
237             size += getMemorySize(propDef.getName());
238             size += getMemorySize(propDef.getId());
239
240             return size;
241         }
242
243         // System.err.println("Unresolved: " + obj.getClass().getName());
244
return 8;
245     }
246
247     /**
248      * Returns if monitoring is enabled.<p>
249      *
250      * @return true if monitoring is enabled
251      */

252     public boolean enabled() {
253
254         return true;
255     }
256
257     /**
258      * Returns the configuration.<p>
259      *
260      * @return the configuration
261      */

262     public CmsMemoryMonitorConfiguration getConfiguration() {
263
264         return m_configuration;
265     }
266
267     /**
268      * Returns the log count.<p>
269      *
270      * @return the log count
271      */

272     public int getLogCount() {
273
274         return m_logCount;
275     }
276
277     /**
278      * Initializes the monitor with the provided configuration.<p>
279      *
280      * @param configuration the configuration to use
281      */

282     public void initialize(CmsMemoryMonitorConfiguration configuration) {
283
284         m_memoryAverage = new CmsMemoryStatus();
285         m_memoryCurrent = new CmsMemoryStatus();
286
287         m_warningSendSinceLastStatus = false;
288         m_warningLoggedSinceLastStatus = false;
289         m_lastEmailWarning = 0;
290         m_lastEmailStatus = 0;
291         m_lastLogStatus = 0;
292         m_lastLogWarning = 0;
293         m_lastClearCache = 0;
294         m_configuration = configuration;
295
296         m_intervalWarning = 720 * 60000;
297         m_maxUsagePercent = 90;
298
299         m_intervalEmail = m_configuration.getEmailInterval() * 1000;
300         m_intervalLog = m_configuration.getLogInterval() * 1000;
301
302         if (m_configuration.getWarningInterval() > 0) {
303             m_intervalWarning = m_configuration.getWarningInterval();
304         }
305         m_intervalWarning *= 1000;
306
307         if (m_configuration.getMaxUsagePercent() > 0) {
308             m_maxUsagePercent = m_configuration.getMaxUsagePercent();
309         }
310
311         if (CmsLog.INIT.isInfoEnabled()) {
312
313             CmsLog.INIT.info(Messages.get().getBundle().key(
314                 Messages.LOG_MM_INTERVAL_LOG_1,
315                 new Integer JavaDoc(m_intervalLog / 1000)));
316             CmsLog.INIT.info(Messages.get().getBundle().key(
317                 Messages.LOG_MM_INTERVAL_EMAIL_1,
318                 new Integer JavaDoc(m_intervalEmail / 1000)));
319             CmsLog.INIT.info(Messages.get().getBundle().key(
320                 Messages.LOG_MM_INTERVAL_WARNING_1,
321                 new Integer JavaDoc(m_intervalWarning / 1000)));
322             CmsLog.INIT.info(Messages.get().getBundle().key(
323                 Messages.LOG_MM_INTERVAL_MAX_USAGE_1,
324                 new Integer JavaDoc(m_intervalWarning / 1000)));
325
326             if ((m_configuration.getEmailReceiver() == null) || (m_configuration.getEmailSender() == null)) {
327                 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_DISABLED_0));
328             } else {
329                 CmsLog.INIT.info(Messages.get().getBundle().key(
330                     Messages.LOG_MM_EMAIL_SENDER_1,
331                     m_configuration.getEmailSender()));
332                 Iterator JavaDoc i = m_configuration.getEmailReceiver().iterator();
333                 int n = 0;
334                 while (i.hasNext()) {
335                     CmsLog.INIT.info(Messages.get().getBundle().key(
336                         Messages.LOG_MM_EMAIL_RECEIVER_2,
337                         new Integer JavaDoc(n + 1),
338                         i.next()));
339                     n++;
340                 }
341             }
342         }
343
344         if (LOG.isDebugEnabled()) {
345             // this will happen only once during system startup
346

347             LOG.debug(Messages.get().getBundle().key(Messages.LOG_MM_CREATED_1, new Date JavaDoc(System.currentTimeMillis())));
348         }
349
350     }
351
352     /**
353      * @see org.opencms.scheduler.I_CmsScheduledJob#launch(CmsObject, Map)
354      */

355     public String JavaDoc launch(CmsObject cms, Map JavaDoc parameters) throws Exception JavaDoc {
356
357         CmsMemoryMonitor monitor = OpenCms.getMemoryMonitor();
358
359         // make sure job is not launched twice
360
if (m_currentlyRunning) {
361             return null;
362         }
363
364         try {
365             m_currentlyRunning = true;
366
367             // update the memory status
368
monitor.updateStatus();
369
370             // check if the system is in a low memory condition
371
if (monitor.lowMemory()) {
372                 // log warning
373
monitor.monitorWriteLog(true);
374                 // send warning email
375
monitor.monitorSendEmail(true);
376                 // clean up caches
377
monitor.clearCaches();
378             }
379
380             // check if regular a log entry must be written
381
if ((System.currentTimeMillis() - monitor.m_lastLogStatus) > monitor.m_intervalLog) {
382                 monitor.monitorWriteLog(false);
383             }
384
385             // check if the memory status email must be send
386
if ((System.currentTimeMillis() - monitor.m_lastEmailStatus) > monitor.m_intervalEmail) {
387                 monitor.monitorSendEmail(false);
388             }
389         } finally {
390             // make sure state is reset even if an error occurs,
391
// otherwise MM will not be executed after an error
392
m_currentlyRunning = false;
393         }
394
395         return null;
396     }
397
398     /**
399      * Returns true if the system runs low on memory.<p>
400      *
401      * @return true if the system runs low on memory
402      */

403     public boolean lowMemory() {
404
405         return ((m_maxUsagePercent > 0) && (m_memoryCurrent.getUsage() > m_maxUsagePercent));
406     }
407
408     /**
409      * Adds a new object to the monitor.<p>
410      *
411      * @param objectName name of the object
412      * @param object the object for monitoring
413      */

414     public void register(String JavaDoc objectName, Object JavaDoc object) {
415
416         m_monitoredObjects.put(objectName, object);
417     }
418
419     /**
420      * Clears the OpenCms caches.<p>
421      */

422     private void clearCaches() {
423
424         if ((m_lastClearCache + INTERVAL_CLEAR) > System.currentTimeMillis()) {
425             // if the cache has already been cleared less then 15 minutes ago we skip this because
426
// clearing the caches to often will hurt system performance and the
427
// setup seems to be in trouble anyway
428
return;
429         }
430         m_lastClearCache = System.currentTimeMillis();
431         if (LOG.isWarnEnabled()) {
432             LOG.warn(Messages.get().getBundle().key(Messages.LOG_CLEAR_CACHE_MEM_CONS_0));
433         }
434         OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.EMPTY_MAP));
435         System.gc();
436     }
437
438     /**
439      * Returns the cache costs of a monitored object.<p>
440      * obj must be of type CmsLruCache
441      *
442      * @param obj the object
443      * @return the cache costs or "-"
444      */

445     private long getCosts(Object JavaDoc obj) {
446
447         long costs = 0;
448         if (obj instanceof CmsLruCache) {
449             costs = ((CmsLruCache)obj).getObjectCosts();
450             if (costs < 0) {
451                 costs = 0;
452             }
453         }
454
455         return costs;
456     }
457
458     /**
459      * Returns the number of items within a monitored object.<p>
460      * obj must be of type CmsLruCache, CmsLruHashMap or Map
461      *
462      * @param obj the object
463      * @return the number of items or "-"
464      */

465     private String JavaDoc getItems(Object JavaDoc obj) {
466
467         if (obj instanceof CmsLruCache) {
468             return Integer.toString(((CmsLruCache)obj).size());
469         }
470         if (obj instanceof Map JavaDoc) {
471             return Integer.toString(((Map JavaDoc)obj).size());
472         }
473         return "-";
474     }
475
476     /**
477      * Returns the total size of key strings within a monitored map.<p>
478      * the keys must be of type String.
479      *
480      * @param map the map
481      * @param depth the max recursion depth for calculation the size
482      * @return total size of key strings
483      */

484     private long getKeySize(Map JavaDoc map, int depth) {
485
486         long keySize = 0;
487         try {
488             Object JavaDoc[] values = map.values().toArray();
489             for (int i = 0, s = values.length; i < s; i++) {
490
491                 Object JavaDoc obj = values[i];
492
493                 if (obj instanceof Map JavaDoc && depth < MAX_DEPTH) {
494                     keySize += getKeySize((Map JavaDoc)obj, depth + 1);
495                     continue;
496                 }
497             }
498             values = null;
499
500             Object JavaDoc[] keys = map.keySet().toArray();
501             for (int i = 0, s = keys.length; i < s; i++) {
502
503                 Object JavaDoc obj = keys[i];
504
505                 if (obj instanceof String JavaDoc) {
506                     String JavaDoc st = (String JavaDoc)obj;
507                     keySize += (st.length() * 2);
508                 }
509             }
510         } catch (ConcurrentModificationException JavaDoc e) {
511             // this might happen since even the .toArray() method internally creates an iterator
512
} catch (Throwable JavaDoc t) {
513             // catch all other exceptions otherwise the whole monitor will stop working
514
if (LOG.isDebugEnabled()) {
515                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
516             }
517         }
518
519         return keySize;
520     }
521
522     /**
523      * Returns the total size of key strings within a monitored object.<p>
524      * obj must be of type map, the keys must be of type String.
525      *
526      * @param obj the object
527      * @return the total size of key strings
528      */

529     private long getKeySize(Object JavaDoc obj) {
530
531         if (obj instanceof Map JavaDoc) {
532             return getKeySize((Map JavaDoc)obj, 1);
533         }
534
535         return 0;
536     }
537
538     /**
539      * Returns the max costs for all items within a monitored object.<p>
540      * obj must be of type CmsLruCache, CmsLruHashMap
541      *
542      * @param obj the object
543      * @return max cost limit or "-"
544      */

545     private String JavaDoc getLimit(Object JavaDoc obj) {
546
547         if (obj instanceof CmsLruCache) {
548             return Integer.toString(((CmsLruCache)obj).getMaxCacheCosts());
549         }
550         if (obj instanceof LRUMap) {
551             return Integer.toString(((LRUMap)obj).maxSize());
552         }
553
554         return "-";
555     }
556
557     /**
558      * Returns the total value size of a list object.<p>
559      *
560      * @param listValue the list object
561      * @param depth the max recursion depth for calculation the size
562      * @return the size of the list object
563      */

564     private long getValueSize(List listValue, int depth) {
565
566         long totalSize = 0;
567         try {
568             Object JavaDoc[] values = listValue.toArray();
569             for (int i = 0, s = values.length; i < s; i++) {
570
571                 Object JavaDoc obj = values[i];
572
573                 if (obj instanceof CmsAccessControlList) {
574                     obj = ((CmsAccessControlList)obj).getPermissionMap();
575                 }
576
577                 if (obj instanceof CmsFlexCacheVariation) {
578                     obj = ((CmsFlexCacheVariation)obj).m_map;
579                 }
580
581                 if (obj instanceof Map JavaDoc && depth < MAX_DEPTH) {
582                     totalSize += getValueSize((Map JavaDoc)obj, depth + 1);
583                     continue;
584                 }
585
586                 if (obj instanceof List && depth < MAX_DEPTH) {
587                     totalSize += getValueSize((List)obj, depth + 1);
588                     continue;
589                 }
590
591                 totalSize += getMemorySize(obj);
592             }
593         } catch (ConcurrentModificationException JavaDoc e) {
594             // this might happen since even the .toArray() method internally creates an iterator
595
} catch (Throwable JavaDoc t) {
596             // catch all other exceptions otherwise the whole monitor will stop working
597
if (LOG.isDebugEnabled()) {
598                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
599             }
600         }
601
602         return totalSize;
603     }
604
605     /**
606      * Returns the total value size of a map object.<p>
607      *
608      * @param mapValue the map object
609      * @param depth the max recursion depth for calculation the size
610      * @return the size of the map object
611      */

612     private long getValueSize(Map JavaDoc mapValue, int depth) {
613
614         long totalSize = 0;
615         try {
616             Object JavaDoc[] values = mapValue.values().toArray();
617             for (int i = 0, s = values.length; i < s; i++) {
618
619                 Object JavaDoc obj = values[i];
620
621                 if (obj instanceof CmsAccessControlList) {
622                     obj = ((CmsAccessControlList)obj).getPermissionMap();
623                 }
624
625                 if (obj instanceof CmsFlexCacheVariation) {
626                     obj = ((CmsFlexCacheVariation)obj).m_map;
627                 }
628
629                 if (obj instanceof Map JavaDoc && depth < MAX_DEPTH) {
630                     totalSize += getValueSize((Map JavaDoc)obj, depth + 1);
631                     continue;
632                 }
633
634                 if (obj instanceof List && depth < MAX_DEPTH) {
635                     totalSize += getValueSize((List)obj, depth + 1);
636                     continue;
637                 }
638
639                 totalSize += getMemorySize(obj);
640             }
641         } catch (ConcurrentModificationException JavaDoc e) {
642             // this might happen since even the .toArray() method internally creates an iterator
643
} catch (Throwable JavaDoc t) {
644             // catch all other exceptions otherwise the whole monitor will stop working
645
if (LOG.isDebugEnabled()) {
646                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
647             }
648         }
649
650         return totalSize;
651     }
652
653     /**
654      * Returns the value sizes of value objects within the monitored object.<p>
655      * obj must be of type map
656      *
657      * @param obj the object
658      * @return the value sizes of value objects or "-"-fields
659      */

660     private long getValueSize(Object JavaDoc obj) {
661
662         if (obj instanceof CmsLruCache) {
663             return ((CmsLruCache)obj).size();
664         }
665
666         if (obj instanceof Map JavaDoc) {
667             return getValueSize((Map JavaDoc)obj, 1);
668         }
669
670         if (obj instanceof List) {
671             return getValueSize((List)obj, 1);
672         }
673
674         try {
675             return getMemorySize(obj);
676         } catch (Exception JavaDoc exc) {
677             return 0;
678         }
679     }
680
681     /**
682      * Sends a warning or status email with OpenCms Memory information.<p>
683      *
684      * @param warning if true, send a memory warning email
685      */

686     private void monitorSendEmail(boolean warning) {
687
688         if ((m_configuration.getEmailSender() == null) || (m_configuration.getEmailReceiver() == null)) {
689             // send no mails if not fully configured
690
return;
691         } else if (warning
692             && (m_warningSendSinceLastStatus && !((m_intervalEmail <= 0) && (System.currentTimeMillis() < (m_lastEmailWarning + m_intervalWarning))))) {
693             // send no warning email if no status email has been send since the last warning
694
// if status is disabled, send no warn email if warn interval has not passed
695
return;
696         } else if ((!warning) && (m_intervalEmail <= 0)) {
697             // if email iterval is <= 0 status email is disabled
698
return;
699         }
700         String JavaDoc date = CmsDateUtil.getDateTimeShort(System.currentTimeMillis());
701         String JavaDoc subject;
702         String JavaDoc content = "";
703         if (warning) {
704             m_warningSendSinceLastStatus = true;
705             m_lastEmailWarning = System.currentTimeMillis();
706             subject = "OpenCms Memory W A R N I N G ["
707                 + OpenCms.getSystemInfo().getServerName().toUpperCase()
708                 + "/"
709                 + date
710                 + "]";
711             content += "W A R N I N G !\nOpenCms memory consumption on server "
712                 + OpenCms.getSystemInfo().getServerName().toUpperCase()
713                 + " has reached a critical level !\n\n"
714                 + "The configured limit is "
715                 + m_maxUsagePercent
716                 + "%\n\n";
717         } else {
718             m_warningSendSinceLastStatus = false;
719             m_lastEmailStatus = System.currentTimeMillis();
720             subject = "OpenCms Memory Status ["
721                 + OpenCms.getSystemInfo().getServerName().toUpperCase()
722                 + "/"
723                 + date
724                 + "]";
725         }
726
727         content += "Memory usage report of OpenCms server "
728             + OpenCms.getSystemInfo().getServerName().toUpperCase()
729             + " at "
730             + date
731             + "\n\n"
732             + "Memory maximum heap size: "
733             + m_memoryCurrent.getMaxMemory()
734             + " mb\n"
735             + "Memory current heap size: "
736             + m_memoryCurrent.getTotalMemory()
737             + " mb\n\n"
738             + "Memory currently used : "
739             + m_memoryCurrent.getUsedMemory()
740             + " mb ("
741             + m_memoryCurrent.getUsage()
742             + "%)\n"
743             + "Memory currently unused : "
744             + m_memoryCurrent.getFreeMemory()
745             + " mb\n\n\n";
746
747         if (warning) {
748             content += "*** Please take action NOW to ensure that no OutOfMemoryException occurs.\n\n\n";
749         }
750
751         CmsSessionManager sm = OpenCms.getSessionManager();
752
753         if (sm != null) {
754             content += "Current status of the sessions:\n\n";
755             content += "Logged in users : " + sm.getSessionCountAuthenticated() + "\n";
756             content += "Currently active sessions: " + sm.getSessionCountCurrent() + "\n";
757             content += "Total created sessions : " + sm.getSessionCountTotal() + "\n\n\n";
758         }
759
760         sm = null;
761
762         content += "Current status of the caches:\n\n";
763         List keyList = Arrays.asList(m_monitoredObjects.keySet().toArray());
764         Collections.sort(keyList);
765         long totalSize = 0;
766         for (Iterator JavaDoc keys = keyList.iterator(); keys.hasNext();) {
767             String JavaDoc key = (String JavaDoc)keys.next();
768             String JavaDoc[] shortKeys = key.split("\\.");
769             String JavaDoc shortKey = shortKeys[shortKeys.length - 2] + '.' + shortKeys[shortKeys.length - 1];
770             PrintfFormat form = new PrintfFormat("%9s");
771             Object JavaDoc obj = m_monitoredObjects.get(key);
772
773             long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj);
774             totalSize += size;
775
776             content += new PrintfFormat("%-42.42s").sprintf(shortKey)
777                 + " "
778                 + "Entries: "
779                 + form.sprintf(getItems(obj))
780                 + " "
781                 + "Limit: "
782                 + form.sprintf(getLimit(obj))
783                 + " "
784                 + "Size: "
785                 + form.sprintf(Long.toString(size))
786                 + "\n";
787         }
788         content += "\nTotal size of cache memory monitored: " + totalSize + " (" + totalSize / 1048576 + ")\n\n";
789
790         String JavaDoc from = m_configuration.getEmailSender();
791         List receivers = new ArrayList JavaDoc();
792         List receiverEmails = m_configuration.getEmailReceiver();
793         try {
794             if (from != null && receiverEmails != null && !receiverEmails.isEmpty()) {
795                 Iterator JavaDoc i = receiverEmails.iterator();
796                 while (i.hasNext()) {
797                     receivers.add(new InternetAddress JavaDoc((String JavaDoc)i.next()));
798                 }
799                 CmsSimpleMail email = new CmsSimpleMail();
800                 email.setFrom(from);
801                 email.setTo(receivers);
802                 email.setSubject(subject);
803                 email.setMsg(content);
804                 new CmsMailTransport(email).send();
805             }
806             if (LOG.isInfoEnabled()) {
807                 if (warning) {
808                     LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_WARNING_EMAIL_SENT_0));
809                 } else {
810                     LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_STATUS_EMAIL_SENT_0));
811                 }
812             }
813         } catch (Exception JavaDoc e) {
814             e.printStackTrace();
815         }
816     }
817
818     /**
819      * Write a warning or status log entry with OpenCms Memory information.<p>
820      *
821      * @param warning if true, write a memory warning log entry
822      */

823     private void monitorWriteLog(boolean warning) {
824
825         if (!LOG.isWarnEnabled()) {
826             // we need at last warn level for this output
827
return;
828         } else if ((!warning) && (!LOG.isInfoEnabled())) {
829             // if not warning we need info level
830
return;
831         } else if (warning
832             && (m_warningLoggedSinceLastStatus && !(((m_intervalLog <= 0) && (System.currentTimeMillis() < (m_lastLogWarning + m_intervalWarning)))))) {
833             // write no warning log if no status log has been written since the last warning
834
// if status is disabled, log no warn entry if warn interval has not passed
835
return;
836         } else if ((!warning) && (m_intervalLog <= 0)) {
837             // if log iterval is <= 0 status log is disabled
838
return;
839         }
840
841         if (warning) {
842             m_lastLogWarning = System.currentTimeMillis();
843             m_warningLoggedSinceLastStatus = true;
844             LOG.warn(Messages.get().getBundle().key(
845                 Messages.LOG_MM_WARNING_MEM_CONSUME_2,
846                 new Long JavaDoc(m_memoryCurrent.getUsage()),
847                 new Integer JavaDoc(m_maxUsagePercent)));
848         } else {
849             m_warningLoggedSinceLastStatus = false;
850             m_lastLogStatus = System.currentTimeMillis();
851         }
852
853         if (warning) {
854             LOG.warn(Messages.get().getBundle().key(
855                 Messages.LOG_MM_WARNING_MEM_STATUS_6,
856                 new Object JavaDoc[] {
857                     new Long JavaDoc(m_memoryCurrent.getMaxMemory()),
858                     new Long JavaDoc(m_memoryCurrent.getTotalMemory()),
859                     new Long JavaDoc(m_memoryCurrent.getFreeMemory()),
860                     new Long JavaDoc(m_memoryCurrent.getUsedMemory()),
861                     new Long JavaDoc(m_memoryCurrent.getUsage()),
862                     new Integer JavaDoc(m_maxUsagePercent)}));
863         } else {
864
865             m_logCount++;
866             LOG.info(Messages.get().getBundle().key(
867                 Messages.LOG_MM_LOG_INFO_2,
868                 OpenCms.getSystemInfo().getServerName().toUpperCase(),
869                 String.valueOf(m_logCount)));
870
871             List keyList = Arrays.asList(m_monitoredObjects.keySet().toArray());
872             Collections.sort(keyList);
873             long totalSize = 0;
874             for (Iterator JavaDoc keys = keyList.iterator(); keys.hasNext();) {
875
876                 String JavaDoc key = (String JavaDoc)keys.next();
877                 Object JavaDoc obj = m_monitoredObjects.get(key);
878
879                 long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj);
880                 totalSize += size;
881
882                 PrintfFormat name1 = new PrintfFormat("%-80s");
883                 PrintfFormat name2 = new PrintfFormat("%-50s");
884                 PrintfFormat form = new PrintfFormat("%9s");
885                 LOG.info(Messages.get().getBundle().key(
886                     Messages.LOG_MM_NOWARN_STATUS_5,
887                     new Object JavaDoc[] {
888                         name1.sprintf(key),
889                         name2.sprintf(obj.getClass().getName()),
890                         form.sprintf(getItems(obj)),
891                         form.sprintf(getLimit(obj)),
892                         form.sprintf(Long.toString(size))}));
893             }
894
895             LOG.info(Messages.get().getBundle().key(
896                 Messages.LOG_MM_WARNING_MEM_STATUS_6,
897                 new Object JavaDoc[] {
898                     new Long JavaDoc(m_memoryCurrent.getMaxMemory()),
899                     new Long JavaDoc(m_memoryCurrent.getTotalMemory()),
900                     new Long JavaDoc(m_memoryCurrent.getFreeMemory()),
901                     new Long JavaDoc(m_memoryCurrent.getUsedMemory()),
902                     new Long JavaDoc(m_memoryCurrent.getUsage()),
903                     new Integer JavaDoc(m_maxUsagePercent),
904                     new Long JavaDoc(totalSize),
905                     new Long JavaDoc(totalSize / 1048576)})
906
907             );
908             LOG.info(Messages.get().getBundle().key(
909                 Messages.LOG_MM_WARNING_MEM_STATUS_AVG_6,
910                 new Object JavaDoc[] {
911                     new Long JavaDoc(m_memoryAverage.getMaxMemory()),
912                     new Long JavaDoc(m_memoryAverage.getTotalMemory()),
913                     new Long JavaDoc(m_memoryAverage.getFreeMemory()),
914                     new Long JavaDoc(m_memoryAverage.getUsedMemory()),
915                     new Long JavaDoc(m_memoryAverage.getUsage()),
916                     new Integer JavaDoc(m_memoryAverage.getCount())}));
917
918             CmsSessionManager sm = OpenCms.getSessionManager();
919
920             if (sm != null) {
921                 LOG.info(Messages.get().getBundle().key(
922                     Messages.LOG_MM_SESSION_STAT_3,
923                     String.valueOf(sm.getSessionCountAuthenticated()),
924                     String.valueOf(sm.getSessionCountCurrent()),
925                     String.valueOf(sm.getSessionCountTotal())));
926             }
927             sm = null;
928
929             for (Iterator JavaDoc i = OpenCms.getSqlManager().getDbPoolNames().iterator(); i.hasNext();) {
930                 String JavaDoc poolname = (String JavaDoc)i.next();
931                 try {
932                     LOG.info(Messages.get().getBundle().key(
933                         Messages.LOG_MM_CONNECTIONS_3,
934                         poolname,
935                         Integer.toString(OpenCms.getSqlManager().getActiveConnections(poolname)),
936                         Integer.toString(OpenCms.getSqlManager().getIdleConnections(poolname))));
937                 } catch (Exception JavaDoc exc) {
938                     LOG.info(Messages.get().getBundle().key(
939                         Messages.LOG_MM_CONNECTIONS_3,
940                         poolname,
941                         Integer.toString(-1),
942                         Integer.toString(-1)));
943                 }
944             }
945
946             LOG.info(Messages.get().getBundle().key(
947                 Messages.LOG_MM_STARTUP_TIME_2,
948                 CmsDateUtil.getDateTimeShort(OpenCms.getSystemInfo().getStartupTime()),
949                 CmsStringUtil.formatRuntime(OpenCms.getSystemInfo().getRuntime())));
950         }
951     }
952
953     /**
954      * Updatres the memory information of the memory monitor.<p>
955      */

956     private void updateStatus() {
957
958         m_memoryCurrent.update();
959         m_memoryAverage.calculateAverage(m_memoryCurrent);
960     }
961 }
Popular Tags