org.opencms.monitor.CmsMemoryMonitor Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software GmbH & Co. KG, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.monitor;
import org.opencms.cache.CmsLruCache;
import org.opencms.cache.CmsMemoryObjectCache;
import org.opencms.cache.CmsVfsMemoryObjectCache;
import org.opencms.configuration.CmsSystemConfiguration;
import org.opencms.db.CmsCacheSettings;
import org.opencms.db.CmsDriverManager;
import org.opencms.db.CmsPublishedResource;
import org.opencms.db.CmsSecurityManager;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsGroup;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsUser;
import org.opencms.flex.CmsFlexCache.CmsFlexCacheVariation;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.lock.CmsLock;
import org.opencms.lock.CmsLockManager;
import org.opencms.mail.CmsMailTransport;
import org.opencms.mail.CmsSimpleMail;
import org.opencms.main.CmsEvent;
import org.opencms.main.CmsLog;
import org.opencms.main.CmsSessionManager;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.publish.CmsPublishHistory;
import org.opencms.publish.CmsPublishJobInfoBean;
import org.opencms.publish.CmsPublishQueue;
import org.opencms.scheduler.I_CmsScheduledJob;
import org.opencms.security.CmsAccessControlList;
import org.opencms.security.CmsOrganizationalUnit;
import org.opencms.security.CmsPermissionSet;
import org.opencms.security.CmsRole;
import org.opencms.security.I_CmsPermissionHandler;
import org.opencms.util.CmsDateUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.util.PrintfFormat;
import org.opencms.xml.CmsXmlContentDefinition;
import org.opencms.xml.CmsXmlEntityResolver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.mail.internet.InternetAddress;
import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.buffer.SynchronizedBuffer;
import org.apache.commons.collections.map.LRUMap;
import org.apache.commons.logging.Log;
import com.google.common.cache.CacheBuilder;
/**
* Monitors OpenCms memory consumption.
*
* The memory monitor also provides all kind of caches used in the OpenCms core.
*
* @since 6.0.0
*/
public class CmsMemoryMonitor implements I_CmsScheduledJob {
/** Cache types. */
public enum CacheType {
/** Access Control Lists cache. */
ACL,
/** Content Definition cache. */
CONTENT_DEFINITION,
/** Group cache. */
GROUP,
/** Has Role cache. */
HAS_ROLE,
/** Locale cache. */
LOCALE,
/** Lock cache. */
LOCK,
/** Memory Object cache. */
MEMORY_OBJECT,
/** Organizational Unit cache. */
ORG_UNIT,
/** Permission cache. */
PERMISSION,
/** Offline Project cache. */
PROJECT,
/** Project resources cache. */
PROJECT_RESOURCES,
/** Property cache. */
PROPERTY,
/** Property List cache. */
PROPERTY_LIST,
/** Publish history cache. */
PUBLISH_HISTORY,
/** Publish queue cache. */
PUBLISH_QUEUE,
/** Published resources cache. */
PUBLISHED_RESOURCES,
/** Resource cache. */
RESOURCE,
/** Resource List cache. */
RESOURCE_LIST,
/** Role List cache. */
ROLE_LIST,
/** User cache. */
USER,
/** User list cache. */
USER_LIST,
/** User Groups cache. */
USERGROUPS,
/** VFS Object cache. */
VFS_OBJECT,
/** XML Entity Permanent cache. */
XML_ENTITY_PERM,
/** XML Entity Temporary cache. */
XML_ENTITY_TEMP;
}
/** The concurrency level for the guava caches. */
private static final int CONCURRENCY_LEVEL = 8;
/** Set interval for clearing the caches to 10 minutes. */
private static final int INTERVAL_CLEAR = 1000 * 60 * 10;
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsMemoryMonitor.class);
/** Flag indicating if monitor is currently running. */
private static boolean m_currentlyRunning;
/** Maximum depth for object size recursion. */
private static final int MAX_DEPTH = 5;
/** Cache for access control lists. */
private Map m_cacheAccessControlList;
/** A temporary cache for XML content definitions. */
private Map m_cacheContentDefinitions;
/** Cache for groups. */
private Map m_cacheGroup;
/** Cache for roles. */
private Map m_cacheHasRoles;
/** A cache for accelerated locale lookup. */
private Map m_cacheLocale;
/** Cache for the resource locks. */
private Map m_cacheLock;
/** The memory object cache map. */
private Map m_cacheMemObject;
/** Cache for organizational units. */
private Map m_cacheOrgUnit;
/** Cache for permission checks. */
private Map m_cachePermission;
/** Cache for offline projects. */
private Map m_cacheProject;
/** Cache for project resources. */
private Map> m_cacheProjectResources;
/** Cache for properties. */
private Map m_cacheProperty;
/** Cache for property lists. */
private Map> m_cachePropertyList;
/** Cache for published resources. */
private Map> m_cachePublishedResources;
/** Cache for resources. */
private Map m_cacheResource;
/** Cache for resource lists. */
private Map> m_cacheResourceList;
/** Cache for role lists. */
private Map> m_cacheRoleLists;
/** Cache for user data. */
private Map m_cacheUser;
/** Cache for user groups. */
private Map> m_cacheUserGroups;
/** Cache for user lists. */
private Map> m_cacheUserList;
/** The vfs memory cache map. */
private Map m_cacheVfsObject;
/** A permanent cache to avoid multiple readings of often used files from the VFS. */
private Map m_cacheXmlPermanentEntity;
/** A temporary cache to avoid multiple readings of often used files from the VFS. */
private Map m_cacheXmlTemporaryEntity;
/** The memory monitor configuration. */
private CmsMemoryMonitorConfiguration m_configuration;
/** Map to keep track of disabled caches. */
private Map m_disabled = new HashMap();
/** Interval in which emails are send. */
private int m_intervalEmail;
/** Interval in which the log is written. */
private int m_intervalLog;
/** Interval between 2 warnings. */
private int m_intervalWarning;
/** The time the caches were last cleared. */
private long m_lastClearCache;
/** The time the last status email was send. */
private long m_lastEmailStatus;
/** The time the last warning email was send. */
private long m_lastEmailWarning;
/** The time the last status log was written. */
private long m_lastLogStatus;
/** The time the last warning log was written. */
private long m_lastLogWarning;
/** The number of times the log entry was written. */
private int m_logCount;
/** Memory percentage to reach to go to warning level. */
private int m_maxUsagePercent;
/** The average memory status. */
private CmsMemoryStatus m_memoryAverage;
/** The current memory status. */
private CmsMemoryStatus m_memoryCurrent;
/** Contains the object to be monitored. */
private Map m_monitoredObjects;
/** Buffer for publish history. */
private Buffer m_publishHistory;
/** Buffer for publish jobs. */
private Buffer m_publishQueue;
/** Flag for memory warning mail send. */
private boolean m_warningLoggedSinceLastStatus;
/** Flag for memory warning mail send. */
private boolean m_warningSendSinceLastStatus;
/**
* Empty constructor, required by OpenCms scheduler.
*/
public CmsMemoryMonitor() {
m_monitoredObjects = new HashMap();
}
/**
* Creates a thread safe LRU cache map based on the guava cache builder.
* Use this instead of synchronized maps for better performance.
*
* @param capacity the cache capacity
*
* @return the cache map
*/
@SuppressWarnings("unchecked")
public static Map createLRUCacheMap(int capacity) {
CacheBuilder, ?> builder = CacheBuilder.newBuilder().concurrencyLevel(CONCURRENCY_LEVEL).maximumSize(
capacity);
builder.build();
return (Map)(builder.build().asMap());
}
/**
* Returns the size of objects that are instances of
* byte[]
, String
, CmsFile
,I_CmsLruCacheObject
.
* For other objects, a size of 0 is returned.
*
* @param obj the object
* @return the size of the object
*/
public static int getMemorySize(Object obj) {
if (obj instanceof I_CmsMemoryMonitorable) {
return ((I_CmsMemoryMonitorable)obj).getMemorySize();
}
if (obj instanceof byte[]) {
// will always be a total of 16 + 8
return 8 + (int)(Math.ceil(((byte[])obj).length / 16.0) * 16.0);
}
if (obj instanceof String) {
// will always be a total of 16 + 24
return 24 + (int)(Math.ceil(((String)obj).length() / 8.0) * 16.0);
}
if (obj instanceof CmsFile) {
CmsFile f = (CmsFile)obj;
if (f.getContents() != null) {
return f.getContents().length + 1024;
} else {
return 1024;
}
}
if (obj instanceof CmsUUID) {
return 184; // worst case if UUID String has been generated
}
if (obj instanceof CmsPermissionSet) {
return 16; // two ints
}
if (obj instanceof CmsResource) {
return 1024; // estimated size
}
if (obj instanceof CmsPublishedResource) {
return 512; // estimated size
}
if (obj instanceof CmsUser) {
return 2048; // estimated size
}
if (obj instanceof CmsGroup) {
return 512; // estimated size
}
if (obj instanceof CmsProject) {
return 512; // estimated size
}
if (obj instanceof Boolean) {
return 8; // one boolean
}
if (obj instanceof CmsProperty) {
int size = 8;
CmsProperty property = (CmsProperty)obj;
size += getMemorySize(property.getName());
if (property.getResourceValue() != null) {
size += getMemorySize(property.getResourceValue());
}
if (property.getStructureValue() != null) {
size += getMemorySize(property.getStructureValue());
}
if (property.getOrigin() != null) {
size += getMemorySize(property.getOrigin());
}
return size;
}
if (obj instanceof CmsPropertyDefinition) {
int size = 8;
CmsPropertyDefinition propDef = (CmsPropertyDefinition)obj;
size += getMemorySize(propDef.getName());
size += getMemorySize(propDef.getId());
return size;
}
return 8;
}
/**
* Returns the total value size of a list object.
*
* @param listValue the list object
* @param depth the max recursion depth for calculation the size
*
* @return the size of the list object
*/
public static long getValueSize(List> listValue, int depth) {
long totalSize = 0;
try {
Object[] values = listValue.toArray();
for (int i = 0, s = values.length; i < s; i++) {
Object obj = values[i];
if (obj instanceof CmsAccessControlList) {
obj = ((CmsAccessControlList)obj).getPermissionMap();
}
if (obj instanceof CmsFlexCacheVariation) {
obj = ((CmsFlexCacheVariation)obj).m_map;
}
if ((obj instanceof Map) && (depth < MAX_DEPTH)) {
totalSize += getValueSize((Map, ?>)obj, depth + 1);
continue;
}
if ((obj instanceof List) && (depth < MAX_DEPTH)) {
totalSize += getValueSize((List>)obj, depth + 1);
continue;
}
totalSize += getMemorySize(obj);
}
} catch (ConcurrentModificationException e) {
// this might happen since even the .toArray() method internally creates an iterator
} catch (Throwable t) {
// catch all other exceptions otherwise the whole monitor will stop working
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
}
}
return totalSize;
}
/**
* Returns the total value size of a map object.
*
* @param mapValue the map object
* @param depth the max recursion depth for calculation the size
*
* @return the size of the map object
*/
public static long getValueSize(Map, ?> mapValue, int depth) {
long totalSize = 0;
try {
Object[] values = mapValue.values().toArray();
for (int i = 0, s = values.length; i < s; i++) {
Object obj = values[i];
if (obj instanceof CmsAccessControlList) {
obj = ((CmsAccessControlList)obj).getPermissionMap();
}
if (obj instanceof CmsFlexCacheVariation) {
obj = ((CmsFlexCacheVariation)obj).m_map;
}
if ((obj instanceof Map) && (depth < MAX_DEPTH)) {
totalSize += getValueSize((Map, ?>)obj, depth + 1);
continue;
}
if ((obj instanceof List) && (depth < MAX_DEPTH)) {
totalSize += getValueSize((List>)obj, depth + 1);
continue;
}
totalSize += getMemorySize(obj);
}
} catch (ConcurrentModificationException e) {
// this might happen since even the .toArray() method internally creates an iterator
} catch (Throwable t) {
// catch all other exceptions otherwise the whole monitor will stop working
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
}
}
return totalSize;
}
/**
* Returns the value sizes of value objects within the monitored object.
*
* @param obj the object
*
* @return the value sizes of value objects or "-"-fields
*/
public static long getValueSize(Object obj) {
if (obj instanceof CmsLruCache) {
return ((CmsLruCache)obj).size();
}
if (obj instanceof Map) {
return getValueSize((Map, ?>)obj, 1);
}
if (obj instanceof List) {
return getValueSize((List>)obj, 1);
}
try {
return getMemorySize(obj);
} catch (Exception exc) {
return 0;
}
}
/**
* Caches the given acl under the given cache key.
*
* @param key the cache key
* @param acl the acl to cache
*/
public void cacheACL(String key, CmsAccessControlList acl) {
if (m_disabled.get(CacheType.ACL) != null) {
return;
}
m_cacheAccessControlList.put(key, acl);
}
/**
* Caches the given content definition under the given cache key.
*
* @param key the cache key
* @param contentDefinition the content definition to cache
*/
public void cacheContentDefinition(String key, CmsXmlContentDefinition contentDefinition) {
if (m_disabled.get(CacheType.CONTENT_DEFINITION) != null) {
return;
}
m_cacheContentDefinitions.put(key, contentDefinition);
}
/**
* Caches the given group under its id AND fully qualified name.
*
* @param group the group to cache
*/
public void cacheGroup(CmsGroup group) {
if (m_disabled.get(CacheType.GROUP) != null) {
return;
}
m_cacheGroup.put(group.getId().toString(), group);
m_cacheGroup.put(group.getName(), group);
}
/**
* Caches the given locale under the given cache key.
*
* @param key the cache key
* @param locale the locale to cache
*/
public void cacheLocale(String key, Locale locale) {
if (m_cacheLocale != null) {
if (m_disabled.get(CacheType.LOCALE) != null) {
return;
}
// this may be accessed before initialization
m_cacheLocale.put(key, locale);
}
}
/**
* Caches the given lock.
*
* The lock is cached by it resource's root path.
*
* @param lock the lock to cache
*/
public void cacheLock(CmsLock lock) {
if (m_disabled.get(CacheType.LOCK) != null) {
return;
}
m_cacheLock.put(lock.getResourceName(), lock);
}
/**
* Caches the given object under the given cache key.
*
* @param key the cache key
* @param obj the object to cache
*/
public void cacheMemObject(String key, Object obj) {
if (m_disabled.get(CacheType.MEMORY_OBJECT) != null) {
return;
}
m_cacheMemObject.put(key, obj);
}
/**
* Caches the given organizational under its id AND the fully qualified name.
*
* @param orgUnit the organizational unit to cache
*/
public void cacheOrgUnit(CmsOrganizationalUnit orgUnit) {
if (m_disabled.get(CacheType.ORG_UNIT) != null) {
return;
}
m_cacheOrgUnit.put(orgUnit.getId().toString(), orgUnit);
m_cacheOrgUnit.put(orgUnit.getName(), orgUnit);
}
/**
* Caches the given permission check result under the given cache key.
*
* @param key the cache key
* @param permission the permission check result to cache
*/
public void cachePermission(String key, I_CmsPermissionHandler.CmsPermissionCheckResult permission) {
if (m_disabled.get(CacheType.PERMISSION) != null) {
return;
}
m_cachePermission.put(key, permission);
}
/**
* Caches the given project under its id AND the fully qualified name.
*
* @param project the project to cache
*/
public void cacheProject(CmsProject project) {
if (m_disabled.get(CacheType.PROJECT) != null) {
return;
}
m_cacheProject.put(project.getUuid().toString(), project);
m_cacheProject.put(project.getName(), project);
}
/**
* Caches the given project resource list under the given cache key.
*
* @param key the cache key
* @param projectResources the project resources to cache
*/
public void cacheProjectResources(String key, List projectResources) {
if (m_disabled.get(CacheType.PROJECT_RESOURCES) != null) {
return;
}
m_cacheProjectResources.put(key, projectResources);
}
/**
* Caches the given property under the given cache key.
*
* @param key the cache key
* @param property the property to cache
*/
public void cacheProperty(String key, CmsProperty property) {
if (m_disabled.get(CacheType.PROPERTY) != null) {
return;
}
m_cacheProperty.put(key, property);
}
/**
* Caches the given property list under the given cache key.
*
* @param key the cache key
* @param propertyList the property list to cache
*/
public void cachePropertyList(String key, List propertyList) {
if (m_disabled.get(CacheType.PROPERTY_LIST) != null) {
return;
}
m_cachePropertyList.put(key, propertyList);
}
/**
* Caches the given published resources list under the given cache key.
*
* @param cacheKey the cache key
* @param publishedResources the published resources list to cache
*/
public void cachePublishedResources(String cacheKey, List publishedResources) {
if (m_disabled.get(CacheType.PUBLISHED_RESOURCES) != null) {
return;
}
m_cachePublishedResources.put(cacheKey, publishedResources);
}
/**
* Caches the given publish job.
*
* @param publishJob the publish job
*/
@SuppressWarnings("unchecked")
public void cachePublishJob(CmsPublishJobInfoBean publishJob) {
if (m_disabled.get(CacheType.PUBLISH_QUEUE) != null) {
return;
}
m_publishQueue.add(publishJob);
}
/**
* Caches the given publish job in the publish job history.
*
* @param publishJob the publish job
*/
@SuppressWarnings("unchecked")
public void cachePublishJobInHistory(CmsPublishJobInfoBean publishJob) {
if (m_disabled.get(CacheType.PUBLISH_HISTORY) != null) {
return;
}
m_publishHistory.add(publishJob);
}
/**
* Caches the given resource under the given cache key.
*
* @param key the cache key
* @param resource the resource to cache
*/
public void cacheResource(String key, CmsResource resource) {
if (m_disabled.get(CacheType.RESOURCE) != null) {
return;
}
m_cacheResource.put(key, resource);
}
/**
* Caches the given resource list under the given cache key.
*
* @param key the cache key
* @param resourceList the resource list to cache
*/
public void cacheResourceList(String key, List resourceList) {
if (m_disabled.get(CacheType.RESOURCE_LIST) != null) {
return;
}
m_cacheResourceList.put(key, resourceList);
}
/**
* Caches the given value under the given cache key.
*
* @param key the cache key
* @param hasRole if the user has the given role
*/
public void cacheRole(String key, boolean hasRole) {
if (m_disabled.get(CacheType.HAS_ROLE) != null) {
return;
}
m_cacheHasRoles.put(key, Boolean.valueOf(hasRole));
}
/**
* Caches the given value under the given cache key.
*
* @param key the cache key
* @param roles the roles of the user
*/
public void cacheRoleList(String key, List roles) {
if (m_disabled.get(CacheType.ROLE_LIST) != null) {
return;
}
m_cacheRoleLists.put(key, roles);
}
/**
* Caches the given user under its id AND the fully qualified name.
*
* @param user the user to cache
*/
public void cacheUser(CmsUser user) {
if (m_disabled.get(CacheType.USER) != null) {
return;
}
m_cacheUser.put(user.getId().toString(), user);
m_cacheUser.put(user.getName(), user);
}
/**
* Caches the given list of user groups under the given cache key.
*
* @param key the cache key
* @param userGroups the list of user groups to cache
*/
public void cacheUserGroups(String key, List userGroups) {
if (m_disabled.get(CacheType.USERGROUPS) != null) {
return;
}
m_cacheUserGroups.put(key, userGroups);
}
/**
* Caches the given list of users under the given cache key.
*
* @param key the cache key
* @param userList the list of users to cache
*/
public void cacheUserList(String key, List userList) {
if (m_disabled.get(CacheType.USER_LIST) != null) {
return;
}
m_cacheUserList.put(key, userList);
}
/**
* Caches the given vfs object under the given cache key.
*
* @param key the cache key
* @param obj the vfs object to cache
*/
public void cacheVfsObject(String key, Object obj) {
if (m_disabled.get(CacheType.VFS_OBJECT) != null) {
return;
}
m_cacheVfsObject.put(key, obj);
}
/**
* Caches the given xml entity under the given system id.
*
* @param systemId the cache key
* @param content the content to cache
*/
public void cacheXmlPermanentEntity(String systemId, byte[] content) {
if (m_disabled.get(CacheType.XML_ENTITY_PERM) != null) {
return;
}
m_cacheXmlPermanentEntity.put(systemId, content);
}
/**
* Caches the given xml entity under the given cache key.
*
* @param key the cache key
* @param content the content to cache
*/
public void cacheXmlTemporaryEntity(String key, byte[] content) {
if (m_disabled.get(CacheType.XML_ENTITY_TEMP) != null) {
return;
}
m_cacheXmlTemporaryEntity.put(key, content);
}
/**
* Clears the access control list cache when access control entries are changed.
*/
public void clearAccessControlListCache() {
flushCache(CacheType.ACL);
flushCache(CacheType.PERMISSION);
clearResourceCache();
}
/**
* Clears almost all internal caches.
*/
public void clearCache() {
clearPrincipalsCache();
flushCache(CacheType.PROJECT);
flushCache(CacheType.RESOURCE);
flushCache(CacheType.RESOURCE_LIST);
flushCache(CacheType.PROPERTY);
flushCache(CacheType.PROPERTY_LIST);
flushCache(CacheType.PROJECT_RESOURCES);
flushCache(CacheType.PUBLISHED_RESOURCES);
}
/**
* Clears all internal principal-related caches.
*/
public void clearPrincipalsCache() {
flushCache(CacheType.USER);
flushCache(CacheType.GROUP);
flushCache(CacheType.ORG_UNIT);
flushCache(CacheType.ACL);
flushCache(CacheType.PERMISSION);
flushCache(CacheType.HAS_ROLE);
flushCache(CacheType.ROLE_LIST);
flushCache(CacheType.USERGROUPS);
flushCache(CacheType.USER_LIST);
}
/**
* Clears all the depending caches when a resource was changed.
*/
public void clearResourceCache() {
flushCache(CacheType.RESOURCE);
flushCache(CacheType.RESOURCE_LIST);
flushCache(CacheType.HAS_ROLE);
flushCache(CacheType.ROLE_LIST);
}
/**
* Clears the user cache for the given user.
*
* @param user the user
*/
public void clearUserCache(CmsUser user) {
uncacheUser(user);
flushCache(CacheType.RESOURCE_LIST);
}
/**
* Disables the given cache.
*
* @param types the cache type to disable
*/
public void disableCache(CacheType... types) {
for (CacheType type : types) {
m_disabled.put(type, Boolean.TRUE);
}
flushCache(types);
}
/**
* Enables the given cache.
*
* @param types the cache type to disable
*/
public void enableCache(CacheType... types) {
for (CacheType type : types) {
m_disabled.remove(type);
}
}
/**
* Returns if monitoring is enabled.
*
* @return true if monitoring is enabled
*/
public boolean enabled() {
return true;
}
/**
* Flushes the ACL cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushACLs() {
flushCache(CacheType.ACL);
}
/**
* Flushes the given cache.
*
* @param types the cache types to flush
*/
public void flushCache(CacheType... types) {
for (CacheType type : types) {
switch (type) {
case ACL:
m_cacheAccessControlList.clear();
break;
case CONTENT_DEFINITION:
m_cacheContentDefinitions.clear();
break;
case GROUP:
m_cacheGroup.clear();
break;
case HAS_ROLE:
m_cacheHasRoles.clear();
break;
case LOCALE:
m_cacheLocale.clear();
break;
case LOCK:
m_cacheLock.clear();
break;
case MEMORY_OBJECT:
m_cacheMemObject.clear();
break;
case ORG_UNIT:
m_cacheOrgUnit.clear();
break;
case PERMISSION:
m_cachePermission.clear();
break;
case PROJECT:
m_cacheProject.clear();
break;
case PROJECT_RESOURCES:
m_cacheProjectResources.clear();
break;
case PROPERTY:
m_cacheProperty.clear();
break;
case PROPERTY_LIST:
m_cachePropertyList.clear();
break;
case PUBLISHED_RESOURCES:
m_cachePublishedResources.clear();
break;
case PUBLISH_HISTORY:
m_publishHistory.clear();
break;
case PUBLISH_QUEUE:
m_publishQueue.clear();
break;
case RESOURCE:
m_cacheResource.clear();
break;
case RESOURCE_LIST:
m_cacheResourceList.clear();
break;
case ROLE_LIST:
m_cacheRoleLists.clear();
break;
case USER:
m_cacheUser.clear();
break;
case USERGROUPS:
m_cacheUserGroups.clear();
break;
case USER_LIST:
m_cacheUserList.clear();
break;
case VFS_OBJECT:
m_cacheVfsObject.clear();
break;
case XML_ENTITY_PERM:
m_cacheXmlPermanentEntity.clear();
break;
case XML_ENTITY_TEMP:
m_cacheXmlTemporaryEntity.clear();
break;
default:
// can't happen
}
}
}
/**
* Flushes the xml content definitions cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushContentDefinitions() {
flushCache(CacheType.CONTENT_DEFINITION);
}
/**
* Flushes the group cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushGroups() {
flushCache(CacheType.GROUP);
}
/**
* Flushes the locale cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushLocales() {
flushCache(CacheType.LOCALE);
}
/**
* Flushes the locks cache.
*
* @param newLocks if not null
the lock cache is replaced by the given map
*/
public void flushLocks(Map newLocks) {
if ((newLocks == null) || newLocks.isEmpty()) {
flushCache(CacheType.LOCK);
return;
}
// initialize new lock cache
Map newLockCache = new ConcurrentHashMap(newLocks);
// register it
register(CmsLockManager.class.getName(), newLockCache);
// save the old cache
Map oldCache = m_cacheLock;
// replace the old by the new cache
m_cacheLock = newLockCache;
// clean up the old cache
oldCache.clear();
}
/**
* Flushes the memory object cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushMemObjects() {
flushCache(CacheType.MEMORY_OBJECT);
}
/**
* Flushes the organizational unit cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushOrgUnits() {
flushCache(CacheType.ORG_UNIT);
}
/**
* Flushes the permission check result cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushPermissions() {
flushCache(CacheType.PERMISSION);
}
/**
* Flushes the project resources cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushProjectResources() {
flushCache(CacheType.PROJECT_RESOURCES);
}
/**
* Flushes the project cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushProjects() {
flushCache(CacheType.PROJECT);
}
/**
* Flushes the property cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushProperties() {
flushCache(CacheType.PROPERTY);
}
/**
* Flushes the property list cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushPropertyLists() {
flushCache(CacheType.PROPERTY_LIST);
}
/**
* Flushes the published resources cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushPublishedResources() {
flushCache(CacheType.PUBLISHED_RESOURCES);
}
/**
* Flushes the publish history.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushPublishJobHistory() {
flushCache(CacheType.PUBLISH_HISTORY);
}
/**
* Flushes the publish queue.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushPublishJobs() {
flushCache(CacheType.PUBLISH_QUEUE);
}
/**
* Flushes the resource list cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushResourceLists() {
flushCache(CacheType.RESOURCE_LIST);
}
/**
* Flushes the resource cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushResources() {
flushCache(CacheType.RESOURCE);
}
/**
* Flushes the role lists cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushRoleLists() {
flushCache(CacheType.ROLE_LIST);
}
/**
* Flushes the roles cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushRoles() {
flushCache(CacheType.HAS_ROLE);
}
/**
* Flushes the user groups cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushUserGroups() {
flushCache(CacheType.USERGROUPS);
flushCache(CacheType.USER_LIST);
}
/**
* Flushes the users cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushUsers() {
flushCache(CacheType.USER);
}
/**
* Flushes the vfs object cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushVfsObjects() {
flushCache(CacheType.VFS_OBJECT);
}
/**
* Flushes the xml permanent entities cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushXmlPermanentEntities() {
flushCache(CacheType.XML_ENTITY_PERM);
}
/**
* Flushes the xml temporary entities cache.
*
* @deprecated use {@link #flushCache(CacheType[])} instead
*/
@Deprecated
public void flushXmlTemporaryEntities() {
flushCache(CacheType.XML_ENTITY_TEMP);
}
/**
* Returns all cached lock root paths.
*
* @return a list of {@link String} objects
*/
public List getAllCachedLockPaths() {
return new ArrayList(m_cacheLock.keySet());
}
/**
* Returns all cached locks.
*
* @return a list of {@link CmsLock} objects
*/
public List getAllCachedLocks() {
return new ArrayList(m_cacheLock.values());
}
/**
* Returns all cached publish jobs in the queue as ordered list.
*
* @return all cached publish jobs
*/
@SuppressWarnings("unchecked")
public List getAllCachedPublishJobs() {
return new ArrayList(m_publishQueue);
}
/**
* Returns all cached publish jobs in the history as ordered list.
*
* @return all cached publish jobs
*/
@SuppressWarnings("unchecked")
public List getAllCachedPublishJobsInHistory() {
return new ArrayList(m_publishHistory);
}
/**
* Returns the ACL cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the ACL cached with the given cache key
*/
public CmsAccessControlList getCachedACL(String key) {
return m_cacheAccessControlList.get(key);
}
/**
* Returns the xml content definition cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the xml content definition cached with the given cache key
*/
public CmsXmlContentDefinition getCachedContentDefinition(String key) {
return m_cacheContentDefinitions.get(key);
}
/**
* Returns the group cached with the given cache key or null
if not found.
*
* @param key the cache key to look for, this may be the group's uuid or the fqn
*
* @return the group cached with the given cache key
*/
public CmsGroup getCachedGroup(String key) {
return m_cacheGroup.get(key);
}
/**
* Returns the locale cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the locale cached with the given cache key
*/
public Locale getCachedLocale(String key) {
if (m_cacheLocale == null) {
// this may be accessed before initialization
return null;
}
return m_cacheLocale.get(key);
}
/**
* Returns the lock cached with the given root path or null
if not found.
*
* @param rootPath the root path to look for
*
* @return the lock cached with the given root path
*/
public CmsLock getCachedLock(String rootPath) {
return m_cacheLock.get(rootPath);
}
/**
* Returns the memory object cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the memory object cached with the given cache key
*/
public Object getCachedMemObject(String key) {
return m_cacheMemObject.get(key);
}
/**
* Returns the organizational unit cached with the given cache key or null
if not found.
*
* @param key the cache key to look for, this may be the organizational unit's uuid or the fqn
*
* @return the organizational unit cached with the given cache key
*/
public CmsOrganizationalUnit getCachedOrgUnit(String key) {
return m_cacheOrgUnit.get(key);
}
/**
* Returns the permission check result cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the permission check result cached with the given cache key
*/
public I_CmsPermissionHandler.CmsPermissionCheckResult getCachedPermission(String key) {
return m_cachePermission.get(key);
}
/**
* Returns the project cached with the given cache key or null
if not found.
*
* @param key the cache key to look for, this may be the project's uuid or the fqn
*
* @return the project cached with the given cache key
*/
public CmsProject getCachedProject(String key) {
return m_cacheProject.get(key);
}
/**
* Returns the project resources list cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the project resources list cached with the given cache key
*/
public List getCachedProjectResources(String key) {
return m_cacheProjectResources.get(key);
}
/**
* Returns the property cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the property cached with the given cache key
*/
public CmsProperty getCachedProperty(String key) {
return m_cacheProperty.get(key);
}
/**
* Returns the property list cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the property list cached with the given cache key
*/
public List getCachedPropertyList(String key) {
return m_cachePropertyList.get(key);
}
/**
* Returns the published resources list cached with the given cache key or null
if not found.
*
* @param cacheKey the cache key to look for
*
* @return the published resources list cached with the given cache key
*/
public List getCachedPublishedResources(String cacheKey) {
return m_cachePublishedResources.get(cacheKey);
}
/**
* Returns the publish job with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the publish job with the given cache key
*/
public CmsPublishJobInfoBean getCachedPublishJob(String key) {
synchronized (m_publishQueue) {
for (Object obj : m_publishQueue) {
CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj;
if (publishJob.getPublishHistoryId().toString().equals(key)) {
return publishJob;
}
}
}
return null;
}
/**
* Returns the publish job from the history with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the publish job with the given cache key
*/
public CmsPublishJobInfoBean getCachedPublishJobInHistory(String key) {
for (Object obj : m_publishHistory) {
CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj;
if (publishJob.getPublishHistoryId().toString().equals(key)) {
return publishJob;
}
}
return null;
}
/**
* Returns the resource cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the resource cached with the given cache key
*/
public CmsResource getCachedResource(String key) {
return m_cacheResource.get(key);
}
/**
* Returns the resource list cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the resource list cached with the given cache key
*/
public List getCachedResourceList(String key) {
return m_cacheResourceList.get(key);
}
/**
* Returns the value cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return if the user has the given role
*/
public Boolean getCachedRole(String key) {
return m_cacheHasRoles.get(key);
}
/**
* Returns the value cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return list of roles
*/
public List getCachedRoleList(String key) {
return m_cacheRoleLists.get(key);
}
/**
* Returns the user cached with the given cache key or null
if not found.
*
* @param key the cache key to look for, this may be the user's uuid or the fqn
*
* @return the user cached with the given cache key
*/
public CmsUser getCachedUser(String key) {
return m_cacheUser.get(key);
}
/**
* Returns the user groups list cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the user groups list cached with the given cache key
*/
public List getCachedUserGroups(String key) {
return m_cacheUserGroups.get(key);
}
/**
* Returns the user list cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the user groups list cached with the given cache key
*/
public List getCachedUserList(String key) {
return m_cacheUserList.get(key);
}
/**
* Returns the vfs object cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the vfs object cached with the given cache key
*/
public Object getCachedVfsObject(String key) {
return m_cacheVfsObject.get(key);
}
/**
* Returns the xml permanent entity content cached with the given systemId or null
if not found.
*
* @param systemId the cache key to look for
*
* @return the xml permanent entity content cached with the given cache key
*/
public byte[] getCachedXmlPermanentEntity(String systemId) {
return m_cacheXmlPermanentEntity.get(systemId);
}
/**
* Returns the xml temporary entity content cached with the given cache key or null
if not found.
*
* @param key the cache key to look for
*
* @return the xml temporary entity content cached with the given cache key
*/
public byte[] getCachedXmlTemporaryEntity(String key) {
return m_cacheXmlTemporaryEntity.get(key);
}
/**
* Returns the configuration.
*
* @return the configuration
*/
public CmsMemoryMonitorConfiguration getConfiguration() {
return m_configuration;
}
/**
* Returns the next publish job from the publish job queue.
*
* @return the next publish job
*/
public CmsPublishJobInfoBean getFirstCachedPublishJob() {
synchronized (m_publishQueue) {
if (!m_publishQueue.isEmpty()) {
return (CmsPublishJobInfoBean)m_publishQueue.get();
} else {
return null;
}
}
}
/**
* Returns the log count.
*
* @return the log count
*/
public int getLogCount() {
return m_logCount;
}
/**
* Returns the current memory status.
*
* @return the memory status
*/
public CmsMemoryStatus getMemoryStatus() {
m_memoryCurrent.update();
return m_memoryCurrent;
}
/**
* Initializes the monitor with the provided configuration.
*
* @param configuration the configuration to use
*/
public void initialize(CmsSystemConfiguration configuration) {
CmsCacheSettings cacheSettings = configuration.getCacheSettings();
m_memoryAverage = new CmsMemoryStatus();
m_memoryCurrent = new CmsMemoryStatus();
m_warningSendSinceLastStatus = false;
m_warningLoggedSinceLastStatus = false;
m_lastEmailWarning = 0;
m_lastEmailStatus = 0;
m_lastLogStatus = 0;
m_lastLogWarning = 0;
m_lastClearCache = 0;
m_configuration = configuration.getCmsMemoryMonitorConfiguration();
m_intervalWarning = 720 * 60000;
m_maxUsagePercent = 90;
m_intervalEmail = m_configuration.getEmailInterval() * 1000;
m_intervalLog = m_configuration.getLogInterval() * 1000;
if (m_configuration.getWarningInterval() > 0) {
m_intervalWarning = m_configuration.getWarningInterval();
}
m_intervalWarning *= 1000;
if (m_configuration.getMaxUsagePercent() > 0) {
m_maxUsagePercent = m_configuration.getMaxUsagePercent();
}
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_LOG_1, new Integer(m_intervalLog / 1000)));
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_EMAIL_1, new Integer(m_intervalEmail / 1000)));
CmsLog.INIT.info(
Messages.get().getBundle().key(
Messages.LOG_MM_INTERVAL_WARNING_1,
new Integer(m_intervalWarning / 1000)));
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_MAX_USAGE_1, new Integer(m_maxUsagePercent)));
if ((m_configuration.getEmailReceiver() == null) || (m_configuration.getEmailSender() == null)) {
CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_DISABLED_0));
} else {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_SENDER_1, m_configuration.getEmailSender()));
Iterator i = m_configuration.getEmailReceiver().iterator();
int n = 0;
while (i.hasNext()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_RECEIVER_2, new Integer(n + 1), i.next()));
n++;
}
}
}
// create and register all system caches
// temporary xml entities cache
m_cacheXmlTemporaryEntity = createLRUCacheMap(128);
register(CmsXmlEntityResolver.class.getName() + ".xmlEntityTemporaryCache", m_cacheXmlTemporaryEntity);
// permanent xml entities cache
m_cacheXmlPermanentEntity = new ConcurrentHashMap(32);
register(CmsXmlEntityResolver.class.getName() + ".xmlEntityPermanentCache", m_cacheXmlPermanentEntity);
// xml content definitions cache
m_cacheContentDefinitions = createLRUCacheMap(64);
register(CmsXmlEntityResolver.class.getName() + ".contentDefinitionsCache", m_cacheContentDefinitions);
// lock cache
m_cacheLock = new ConcurrentHashMap();
register(CmsLockManager.class.getName(), m_cacheLock);
// locale cache
m_cacheLocale = new ConcurrentHashMap();
register(CmsLocaleManager.class.getName(), m_cacheLocale);
// permissions cache
m_cachePermission = createLRUCacheMap(cacheSettings.getPermissionCacheSize());
register(CmsSecurityManager.class.getName(), m_cachePermission);
// user cache
m_cacheUser = createLRUCacheMap(cacheSettings.getUserCacheSize());
register(CmsDriverManager.class.getName() + ".userCache", m_cacheUser);
// user list cache
m_cacheUserList = createLRUCacheMap(cacheSettings.getUserCacheSize());
register(CmsDriverManager.class.getName() + ".userListCache", m_cacheUserList);
// group cache
m_cacheGroup = createLRUCacheMap(cacheSettings.getGroupCacheSize());
register(CmsDriverManager.class.getName() + ".groupCache", m_cacheGroup);
// organizational unit cache
m_cacheOrgUnit = createLRUCacheMap(cacheSettings.getOrgUnitCacheSize());
register(CmsDriverManager.class.getName() + ".orgUnitCache", m_cacheOrgUnit);
// user groups list cache
m_cacheUserGroups = createLRUCacheMap(cacheSettings.getUserGroupsCacheSize());
register(CmsDriverManager.class.getName() + ".userGroupsCache", m_cacheUserGroups);
// project cache
m_cacheProject = createLRUCacheMap(cacheSettings.getProjectCacheSize());
register(CmsDriverManager.class.getName() + ".projectCache", m_cacheProject);
// project resources cache cache
m_cacheProjectResources = createLRUCacheMap(cacheSettings.getProjectResourcesCacheSize());
register(CmsDriverManager.class.getName() + ".projectResourcesCache", m_cacheProjectResources);
// publish history
int size = configuration.getPublishManager().getPublishHistorySize();
Buffer buffer = CmsPublishHistory.getQueue(size);
m_publishHistory = SynchronizedBuffer.decorate(buffer);
register(CmsPublishHistory.class.getName() + ".publishHistory", buffer);
// publish queue
buffer = CmsPublishQueue.getQueue();
m_publishQueue = SynchronizedBuffer.decorate(buffer);
register(CmsPublishQueue.class.getName() + ".publishQueue", buffer);
// resource cache
m_cacheResource = createLRUCacheMap(cacheSettings.getResourceCacheSize());
register(CmsDriverManager.class.getName() + ".resourceCache", m_cacheResource);
// roles cache
m_cacheHasRoles = createLRUCacheMap(cacheSettings.getRolesCacheSize());
register(CmsDriverManager.class.getName() + ".rolesCache", m_cacheHasRoles);
// role lists cache
m_cacheRoleLists = createLRUCacheMap(cacheSettings.getRolesCacheSize());
register(CmsDriverManager.class.getName() + ".roleListsCache", m_cacheRoleLists);
// resource list cache
m_cacheResourceList = createLRUCacheMap(cacheSettings.getResourcelistCacheSize());
register(CmsDriverManager.class.getName() + ".resourceListCache", m_cacheResourceList);
// property cache
m_cacheProperty = createLRUCacheMap(cacheSettings.getPropertyCacheSize());
register(CmsDriverManager.class.getName() + ".propertyCache", m_cacheProperty);
// property list cache
m_cachePropertyList = createLRUCacheMap(cacheSettings.getPropertyListsCacheSize());
register(CmsDriverManager.class.getName() + ".propertyListCache", m_cachePropertyList);
// published resources list cache
m_cachePublishedResources = createLRUCacheMap(5);
register(CmsDriverManager.class.getName() + ".publishedResourcesCache", m_cachePublishedResources);
// acl cache
m_cacheAccessControlList = createLRUCacheMap(cacheSettings.getAclCacheSize());
register(CmsDriverManager.class.getName() + ".accessControlListCache", m_cacheAccessControlList);
// vfs object cache
m_cacheVfsObject = new ConcurrentHashMap();
register(CmsVfsMemoryObjectCache.class.getName(), m_cacheVfsObject);
// memory object cache
m_cacheMemObject = new ConcurrentHashMap();
register(CmsMemoryObjectCache.class.getName(), m_cacheMemObject);
if (LOG.isDebugEnabled()) {
// this will happen only once during system startup
LOG.debug(Messages.get().getBundle().key(Messages.LOG_MM_CREATED_1, new Date(System.currentTimeMillis())));
}
}
/**
* Checks if the property cache is enabled.
*
* @return true
if the property cache is enabled
*
* @deprecated use {@link #isEnabled(CacheType)} instead
*/
@Deprecated
public boolean isCacheProperty() {
return isEnabled(CacheType.PROPERTY);
}
/**
* Checks if the property list cache is enabled.
*
* @return true
if the property list cache is enabled
*
* @deprecated use {@link #isEnabled(CacheType)} instead
*/
@Deprecated
public boolean isCachePropertyList() {
return isEnabled(CacheType.PROPERTY_LIST);
}
/**
* Checks if the resource cache is enabled.
*
* @return true
if the resource cache is enabled
*
* @deprecated use {@link #isEnabled(CacheType)} instead
*/
@Deprecated
public boolean isCacheResource() {
return isEnabled(CacheType.RESOURCE);
}
/**
* Checks if the resource list cache is enabled.
*
* @return true
if the resource list cache is enabled
*
* @deprecated use {@link #isEnabled(CacheType)} instead
*/
@Deprecated
public boolean isCacheResourceList() {
return isEnabled(CacheType.RESOURCE_LIST);
}
/**
* Checks if the given cache is enabled.
*
* @param type the cache type to check
*
* @return true
if the given cache is enabled
*/
public boolean isEnabled(CacheType type) {
return (m_disabled.get(type) == null);
}
/**
* Checks if there is a registered monitored object with the given key.
*
* @param key the key to look for
*
* @return true
if there is a registered monitored object with the given key
*/
public boolean isMonitoring(String key) {
return (m_monitoredObjects.get(key) != null);
}
/**
* @see org.opencms.scheduler.I_CmsScheduledJob#launch(CmsObject, Map)
*/
public String launch(CmsObject cms, Map parameters) throws Exception {
CmsMemoryMonitor monitor = OpenCms.getMemoryMonitor();
// make sure job is not launched twice
if (m_currentlyRunning) {
return null;
}
try {
m_currentlyRunning = true;
// update the memory status
monitor.updateStatus();
// check if the system is in a low memory condition
if (monitor.lowMemory()) {
// log warning
monitor.monitorWriteLog(true);
// send warning email
monitor.monitorSendEmail(true);
// clean up caches
monitor.clearCaches();
}
// check if regular a log entry must be written
if ((System.currentTimeMillis() - monitor.m_lastLogStatus) > monitor.m_intervalLog) {
monitor.monitorWriteLog(false);
}
// check if the memory status email must be send
if ((System.currentTimeMillis() - monitor.m_lastEmailStatus) > monitor.m_intervalEmail) {
monitor.monitorSendEmail(false);
}
} finally {
// make sure state is reset even if an error occurs,
// otherwise MM will not be executed after an error
m_currentlyRunning = false;
}
return null;
}
/**
* Returns true if the system runs low on memory.
*
* @return true if the system runs low on memory
*/
public boolean lowMemory() {
return ((m_maxUsagePercent > 0) && (m_memoryCurrent.getUsage() > m_maxUsagePercent));
}
/**
* Adds a new object to the monitor.
*
* @param objectName name of the object
* @param object the object for monitoring
*/
public void register(String objectName, Object object) {
if (enabled()) {
m_monitoredObjects.put(objectName, object);
}
}
/**
* Checks if some kind of persistence is required.
*
* This could be overwritten in a distributed environment.
*
* @return true
if some kind of persistence is required
*/
public boolean requiresPersistency() {
return true;
}
/**
* Sets if the property cache is enabled.
*
* @param cacheProperty if the property cache is enabled
*
* @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead
*/
@Deprecated
public void setCacheProperty(boolean cacheProperty) {
if (cacheProperty) {
enableCache(CacheType.PROPERTY);
} else {
disableCache(CacheType.PROPERTY);
}
}
/**
* Sets if the property list cache is enabled.
*
* @param cachePropertyList if the property list cache is enabled
*
* @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead
*/
@Deprecated
public void setCachePropertyList(boolean cachePropertyList) {
if (cachePropertyList) {
enableCache(CacheType.PROPERTY_LIST);
} else {
disableCache(CacheType.PROPERTY_LIST);
}
}
/**
* Sets if the resource cache is enabled.
*
* @param cacheResource if the resource cache is enabled
*
* @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead
*/
@Deprecated
public void setCacheResource(boolean cacheResource) {
if (cacheResource) {
enableCache(CacheType.RESOURCE);
} else {
disableCache(CacheType.RESOURCE);
}
}
/**
* Sets if the resource list cache is enabled.
*
* @param cacheResourceList if the resource list cache is enabled
*
* @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead
*/
@Deprecated
public void setCacheResourceList(boolean cacheResourceList) {
if (cacheResourceList) {
enableCache(CacheType.RESOURCE_LIST);
} else {
disableCache(CacheType.RESOURCE_LIST);
}
}
/**
* Flushes all cached objects.
*
* @throws Exception if something goes wrong
*/
public void shutdown() throws Exception {
for (CacheType type : CacheType.values()) {
flushCache(type);
}
}
/**
* Removes the given xml content definition from the cache.
*
* @param key the cache key to remove from cache
*/
public void uncacheContentDefinition(String key) {
m_cacheContentDefinitions.remove(key);
}
/**
* Removes the given group from the cache.
*
* The group is removed by name AND also by uuid.
*
* @param group the group to remove from cache
*/
public void uncacheGroup(CmsGroup group) {
m_cacheGroup.remove(group.getId().toString());
m_cacheGroup.remove(group.getName());
}
/**
* Removes the cached lock for the given root path from the cache.
*
* @param rootPath the root path of the lock to remove from cache
*/
public void uncacheLock(String rootPath) {
m_cacheLock.remove(rootPath);
}
/**
* Removes the given organizational unit from the cache.
*
* The organizational unit is removed by name AND also by uuid.
*
* @param orgUnit the organizational unit to remove from cache
*/
public void uncacheOrgUnit(CmsOrganizationalUnit orgUnit) {
m_cacheOrgUnit.remove(orgUnit.getId().toString());
m_cacheOrgUnit.remove(orgUnit.getName());
}
/**
* Removes the given project from the cache.
*
* The project is removed by name AND also by uuid.
*
* @param project the project to remove from cache
*/
public void uncacheProject(CmsProject project) {
m_cacheProject.remove(project.getUuid().toString());
m_cacheProject.remove(project.getName());
}
/**
* Removes the given publish job from the cache.
*
* @param publishJob the publish job to remove
*/
public void uncachePublishJob(CmsPublishJobInfoBean publishJob) {
m_publishQueue.remove(publishJob);
}
/**
* Removes the given publish job from the history.
*
* @param publishJob the publish job to remove
*/
public void uncachePublishJobInHistory(CmsPublishJobInfoBean publishJob) {
m_publishHistory.remove(publishJob);
}
/**
* Removes the given user from the cache.
*
* The user is removed by name AND also by uuid.
*
* @param user the user to remove from cache
*/
public void uncacheUser(CmsUser user) {
m_cacheUser.remove(user.getId().toString());
m_cacheUser.remove(user.getName());
}
/**
* Removes the given vfs object from the cache.
*
* @param key the cache key to remove from cache
*/
public void uncacheVfsObject(String key) {
m_cacheVfsObject.remove(key);
}
/**
* Removes the given xml temporary entity from the cache.
*
* @param key the cache key to remove from cache
*/
public void uncacheXmlTemporaryEntity(String key) {
m_cacheXmlTemporaryEntity.remove(key);
}
/**
* Clears the OpenCms caches.
*/
protected void clearCaches() {
if ((m_lastClearCache + INTERVAL_CLEAR) > System.currentTimeMillis()) {
// if the cache has already been cleared less then 15 minutes ago we skip this because
// clearing the caches to often will hurt system performance and the
// setup seems to be in trouble anyway
return;
}
m_lastClearCache = System.currentTimeMillis();
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_CLEAR_CACHE_MEM_CONS_0));
}
OpenCms.fireCmsEvent(
new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections. emptyMap()));
System.gc();
}
/**
* Returns the cache costs of a monitored object.
*
* obj
must be of type {@link CmsLruCache}.
*
* @param obj the object
*
* @return the cache costs or "-"
*/
protected long getCosts(Object obj) {
long costs = 0;
if (obj instanceof CmsLruCache) {
costs = ((CmsLruCache)obj).getObjectCosts();
if (costs < 0) {
costs = 0;
}
}
return costs;
}
/**
* Returns the number of items within a monitored object.
*
* obj
must be of type {@link CmsLruCache} or {@link Map}.
*
* @param obj the object
*
* @return the number of items or "-"
*/
protected String getItems(Object obj) {
if (obj instanceof CmsLruCache) {
return Integer.toString(((CmsLruCache)obj).size());
}
if (obj instanceof Map) {
return Integer.toString(((Map, ?>)obj).size());
}
return "-";
}
/**
* Returns the total size of key strings within a monitored map.
*
* The keys must be of type {@link String}.
*
* @param map the map
* @param depth the max recursion depth for calculation the size
*
* @return total size of key strings
*/
protected long getKeySize(Map, ?> map, int depth) {
long keySize = 0;
try {
Object[] values = map.values().toArray();
for (int i = 0, s = values.length; i < s; i++) {
Object obj = values[i];
if ((obj instanceof Map) && (depth < MAX_DEPTH)) {
keySize += getKeySize((Map, ?>)obj, depth + 1);
continue;
}
}
values = null;
Object[] keys = map.keySet().toArray();
for (int i = 0, s = keys.length; i < s; i++) {
Object obj = keys[i];
if (obj instanceof String) {
String st = (String)obj;
keySize += (st.length() * 2);
}
}
} catch (ConcurrentModificationException e) {
// this might happen since even the .toArray() method internally creates an iterator
} catch (Throwable t) {
// catch all other exceptions otherwise the whole monitor will stop working
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage()));
}
}
return keySize;
}
/**
* Returns the total size of key strings within a monitored object.
*
* obj
must be of type {@link Map}, the keys must be of type {@link String}.
*
* @param obj the object
*
* @return the total size of key strings
*/
protected long getKeySize(Object obj) {
if (obj instanceof Map) {
return getKeySize((Map, ?>)obj, 1);
}
return 0;
}
/**
* Returns the max costs for all items within a monitored object.
*
* obj
must be of type {@link CmsLruCache} or {@link LRUMap}.
*
* @param obj the object
*
* @return max cost limit or "-"
*/
protected String getLimit(Object obj) {
if (obj instanceof CmsLruCache) {
return Long.toString(((CmsLruCache)obj).getMaxCacheCosts());
}
if (obj instanceof LRUMap) {
return Integer.toString(((LRUMap)obj).maxSize());
}
return "-";
}
/**
* Sends a warning or status email with OpenCms Memory information.
*
* @param warning if true, send a memory warning email
*/
protected void monitorSendEmail(boolean warning) {
if ((m_configuration.getEmailSender() == null) || (m_configuration.getEmailReceiver() == null)) {
// send no mails if not fully configured
return;
} else if (warning
&& (m_warningSendSinceLastStatus
&& !((m_intervalEmail <= 0)
&& (System.currentTimeMillis() < (m_lastEmailWarning + m_intervalWarning))))) {
// send no warning email if no status email has been send since the last warning
// if status is disabled, send no warn email if warn interval has not passed
return;
} else if ((!warning) && (m_intervalEmail <= 0)) {
// if email iterval is <= 0 status email is disabled
return;
}
String date = CmsDateUtil.getDateTimeShort(System.currentTimeMillis());
String subject;
String content = "";
if (warning) {
m_warningSendSinceLastStatus = true;
m_lastEmailWarning = System.currentTimeMillis();
subject = "OpenCms Memory W A R N I N G ["
+ OpenCms.getSystemInfo().getServerName().toUpperCase()
+ "/"
+ date
+ "]";
content += "W A R N I N G !\nOpenCms memory consumption on server "
+ OpenCms.getSystemInfo().getServerName().toUpperCase()
+ " has reached a critical level !\n\n"
+ "The configured limit is "
+ m_maxUsagePercent
+ "%\n\n";
} else {
m_warningSendSinceLastStatus = false;
m_lastEmailStatus = System.currentTimeMillis();
subject = "OpenCms Memory Status ["
+ OpenCms.getSystemInfo().getServerName().toUpperCase()
+ "/"
+ date
+ "]";
}
content += "Memory usage report of OpenCms server "
+ OpenCms.getSystemInfo().getServerName().toUpperCase()
+ " at "
+ date
+ "\n\n"
+ "Memory maximum heap size: "
+ m_memoryCurrent.getMaxMemory()
+ " mb\n"
+ "Memory current heap size: "
+ m_memoryCurrent.getTotalMemory()
+ " mb\n\n"
+ "Memory currently used : "
+ m_memoryCurrent.getUsedMemory()
+ " mb ("
+ m_memoryCurrent.getUsage()
+ "%)\n"
+ "Memory currently unused : "
+ m_memoryCurrent.getFreeMemory()
+ " mb\n\n\n";
if (warning) {
content += "*** Please take action NOW to ensure that no OutOfMemoryException occurs.\n\n\n";
}
CmsSessionManager sm = OpenCms.getSessionManager();
if (sm != null) {
content += "Current status of the sessions:\n\n";
content += "Logged in users : " + sm.getSessionCountAuthenticated() + "\n";
content += "Currently active sessions: " + sm.getSessionCountCurrent() + "\n";
content += "Total created sessions : " + sm.getSessionCountTotal() + "\n\n\n";
}
sm = null;
content += "Current status of the caches:\n\n";
List keyList = new ArrayList(m_monitoredObjects.keySet());
Collections.sort(keyList);
long totalSize = 0;
for (Iterator keys = keyList.iterator(); keys.hasNext();) {
String key = keys.next();
String[] shortKeys = key.split("\\.");
String shortKey = shortKeys[shortKeys.length - 2] + '.' + shortKeys[shortKeys.length - 1];
PrintfFormat form = new PrintfFormat("%9s");
Object obj = m_monitoredObjects.get(key);
long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj);
totalSize += size;
content += new PrintfFormat("%-42.42s").sprintf(shortKey)
+ " "
+ "Entries: "
+ form.sprintf(getItems(obj))
+ " "
+ "Limit: "
+ form.sprintf(getLimit(obj))
+ " "
+ "Size: "
+ form.sprintf(Long.toString(size))
+ "\n";
}
content += "\nTotal size of cache memory monitored: " + totalSize + " (" + (totalSize / 1048576) + ")\n\n";
String from = m_configuration.getEmailSender();
List receivers = new ArrayList();
List receiverEmails = m_configuration.getEmailReceiver();
try {
if ((from != null) && (receiverEmails != null) && !receiverEmails.isEmpty()) {
Iterator i = receiverEmails.iterator();
while (i.hasNext()) {
receivers.add(new InternetAddress(i.next()));
}
CmsSimpleMail email = new CmsSimpleMail();
email.setFrom(from);
email.setTo(receivers);
email.setSubject(subject);
email.setMsg(content);
new CmsMailTransport(email).send();
}
if (LOG.isInfoEnabled()) {
if (warning) {
LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_WARNING_EMAIL_SENT_0));
} else {
LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_STATUS_EMAIL_SENT_0));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Write a warning or status log entry with OpenCms Memory information.
*
* @param warning if true, write a memory warning log entry
*/
protected void monitorWriteLog(boolean warning) {
if (!LOG.isWarnEnabled()) {
// we need at last warn level for this output
return;
} else if ((!warning) && (!LOG.isInfoEnabled())) {
// if not warning we need info level
return;
} else if (warning
&& (m_warningLoggedSinceLastStatus
&& !(((m_intervalLog <= 0)
&& (System.currentTimeMillis() < (m_lastLogWarning + m_intervalWarning)))))) {
// write no warning log if no status log has been written since the last warning
// if status is disabled, log no warn entry if warn interval has not passed
return;
} else if ((!warning) && (m_intervalLog <= 0)) {
// if log interval is <= 0 status log is disabled
return;
}
if (warning) {
m_lastLogWarning = System.currentTimeMillis();
m_warningLoggedSinceLastStatus = true;
LOG.warn(
Messages.get().getBundle().key(
Messages.LOG_MM_WARNING_MEM_CONSUME_2,
new Long(m_memoryCurrent.getUsage()),
new Integer(m_maxUsagePercent)));
} else {
m_warningLoggedSinceLastStatus = false;
m_lastLogStatus = System.currentTimeMillis();
}
if (warning) {
LOG.warn(
Messages.get().getBundle().key(
Messages.LOG_MM_WARNING_MEM_STATUS_6,
new Object[] {
new Long(m_memoryCurrent.getMaxMemory()),
new Long(m_memoryCurrent.getTotalMemory()),
new Long(m_memoryCurrent.getFreeMemory()),
new Long(m_memoryCurrent.getUsedMemory()),
new Long(m_memoryCurrent.getUsage()),
new Integer(m_maxUsagePercent)}));
} else {
m_logCount++;
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_LOG_INFO_2,
OpenCms.getSystemInfo().getServerName().toUpperCase(),
String.valueOf(m_logCount)));
List keyList = new ArrayList(m_monitoredObjects.keySet());
Collections.sort(keyList);
long totalSize = 0;
for (Iterator keys = keyList.iterator(); keys.hasNext();) {
String key = keys.next();
Object obj = m_monitoredObjects.get(key);
long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj);
totalSize += size;
PrintfFormat name1 = new PrintfFormat("%-80s");
PrintfFormat name2 = new PrintfFormat("%-50s");
PrintfFormat form = new PrintfFormat("%9s");
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_NOWARN_STATUS_5,
new Object[] {
name1.sprintf(key),
name2.sprintf(obj.getClass().getName()),
form.sprintf(getItems(obj)),
form.sprintf(getLimit(obj)),
form.sprintf(Long.toString(size))}));
}
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_WARNING_MEM_STATUS_6,
new Object[] {
new Long(m_memoryCurrent.getMaxMemory()),
new Long(m_memoryCurrent.getTotalMemory()),
new Long(m_memoryCurrent.getFreeMemory()),
new Long(m_memoryCurrent.getUsedMemory()),
new Long(m_memoryCurrent.getUsage()),
new Integer(m_maxUsagePercent),
new Long(totalSize),
new Long(totalSize / 1048576)})
);
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_WARNING_MEM_STATUS_AVG_6,
new Object[] {
new Long(m_memoryAverage.getMaxMemory()),
new Long(m_memoryAverage.getTotalMemory()),
new Long(m_memoryAverage.getFreeMemory()),
new Long(m_memoryAverage.getUsedMemory()),
new Long(m_memoryAverage.getUsage()),
new Integer(m_memoryAverage.getCount())}));
CmsSessionManager sm = OpenCms.getSessionManager();
if (sm != null) {
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_SESSION_STAT_3,
String.valueOf(sm.getSessionCountAuthenticated()),
String.valueOf(sm.getSessionCountCurrent()),
String.valueOf(sm.getSessionCountTotal())));
}
sm = null;
for (Iterator i = OpenCms.getSqlManager().getDbPoolUrls().iterator(); i.hasNext();) {
String poolname = i.next();
try {
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_CONNECTIONS_3,
poolname,
Integer.toString(OpenCms.getSqlManager().getActiveConnections(poolname)),
Integer.toString(OpenCms.getSqlManager().getIdleConnections(poolname))));
} catch (Exception exc) {
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_CONNECTIONS_3,
poolname,
Integer.toString(-1),
Integer.toString(-1)));
}
}
LOG.info(
Messages.get().getBundle().key(
Messages.LOG_MM_STARTUP_TIME_2,
CmsDateUtil.getDateTimeShort(OpenCms.getSystemInfo().getStartupTime()),
CmsStringUtil.formatRuntime(OpenCms.getSystemInfo().getRuntime())));
}
}
/**
* Updates the memory information of the memory monitor.
*/
protected void updateStatus() {
m_memoryCurrent.update();
m_memoryAverage.calculateAverage(m_memoryCurrent);
}
}