001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.monitor; 029 030import org.opencms.cache.CmsLruCache; 031import org.opencms.cache.CmsMemoryObjectCache; 032import org.opencms.cache.CmsVfsMemoryObjectCache; 033import org.opencms.configuration.CmsSystemConfiguration; 034import org.opencms.db.CmsCacheSettings; 035import org.opencms.db.CmsDriverManager; 036import org.opencms.db.CmsDriverManager.ResourceOUCacheKey; 037import org.opencms.db.CmsDriverManager.ResourceOUMap; 038import org.opencms.db.CmsPublishedResource; 039import org.opencms.db.CmsSecurityManager; 040import org.opencms.file.CmsFile; 041import org.opencms.file.CmsGroup; 042import org.opencms.file.CmsObject; 043import org.opencms.file.CmsProject; 044import org.opencms.file.CmsProperty; 045import org.opencms.file.CmsPropertyDefinition; 046import org.opencms.file.CmsResource; 047import org.opencms.file.CmsUser; 048import org.opencms.flex.CmsFlexCache.CmsFlexCacheVariation; 049import org.opencms.i18n.CmsLocaleManager; 050import org.opencms.lock.CmsLock; 051import org.opencms.lock.CmsLockManager; 052import org.opencms.mail.CmsMailTransport; 053import org.opencms.mail.CmsSimpleMail; 054import org.opencms.main.CmsEvent; 055import org.opencms.main.CmsLog; 056import org.opencms.main.CmsSessionManager; 057import org.opencms.main.I_CmsEventListener; 058import org.opencms.main.OpenCms; 059import org.opencms.publish.CmsPublishHistory; 060import org.opencms.publish.CmsPublishJobInfoBean; 061import org.opencms.publish.CmsPublishQueue; 062import org.opencms.scheduler.I_CmsScheduledJob; 063import org.opencms.security.CmsAccessControlList; 064import org.opencms.security.CmsOrganizationalUnit; 065import org.opencms.security.CmsPermissionSet; 066import org.opencms.security.CmsRole; 067import org.opencms.security.I_CmsPermissionHandler; 068import org.opencms.util.CmsDateUtil; 069import org.opencms.util.CmsStringUtil; 070import org.opencms.util.CmsUUID; 071import org.opencms.util.PrintfFormat; 072import org.opencms.xml.CmsXmlContentDefinition; 073import org.opencms.xml.CmsXmlEntityResolver; 074 075import java.util.ArrayList; 076import java.util.Collections; 077import java.util.ConcurrentModificationException; 078import java.util.Date; 079import java.util.HashMap; 080import java.util.Iterator; 081import java.util.List; 082import java.util.Locale; 083import java.util.Map; 084import java.util.concurrent.ConcurrentHashMap; 085import java.util.concurrent.TimeUnit; 086 087import javax.mail.internet.InternetAddress; 088 089import org.apache.commons.collections.Buffer; 090import org.apache.commons.collections.buffer.SynchronizedBuffer; 091import org.apache.commons.collections.map.LRUMap; 092import org.apache.commons.logging.Log; 093 094import com.google.common.cache.CacheBuilder; 095import com.google.common.cache.CacheLoader; 096import com.google.common.cache.LoadingCache; 097 098/** 099 * Monitors OpenCms memory consumption.<p> 100 * 101 * The memory monitor also provides all kind of caches used in the OpenCms core.<p> 102 * 103 * @since 6.0.0 104 */ 105public class CmsMemoryMonitor implements I_CmsScheduledJob { 106 107 /** Cache types. */ 108 public enum CacheType { 109 /** Access Control Lists cache. */ 110 ACL, 111 /** Content Definition cache. */ 112 CONTENT_DEFINITION, 113 /** Group cache. */ 114 GROUP, 115 /** Has Role cache. */ 116 HAS_ROLE, 117 /** Locale cache. */ 118 LOCALE, 119 /** Lock cache. */ 120 LOCK, 121 /** Memory Object cache. */ 122 MEMORY_OBJECT, 123 /** Organizational Unit cache. */ 124 ORG_UNIT, 125 /** Permission cache. */ 126 PERMISSION, 127 /** Offline Project cache. */ 128 PROJECT, 129 /** Project resources cache. */ 130 PROJECT_RESOURCES, 131 /** Property cache. */ 132 PROPERTY, 133 /** Property List cache. */ 134 PROPERTY_LIST, 135 /** Publish history cache. */ 136 PUBLISH_HISTORY, 137 /** Publish queue cache. */ 138 PUBLISH_QUEUE, 139 /** Published resources cache. */ 140 PUBLISHED_RESOURCES, 141 /** Resource cache. */ 142 RESOURCE, 143 /** Resource List cache. */ 144 RESOURCE_LIST, 145 /** Role List cache. */ 146 ROLE_LIST, 147 /** User cache. */ 148 USER, 149 /** User list cache. */ 150 USER_LIST, 151 /** User Groups cache. */ 152 USERGROUPS, 153 /** VFS Object cache. */ 154 VFS_OBJECT, 155 /** XML Entity Permanent cache. */ 156 XML_ENTITY_PERM, 157 /** XML Entity Temporary cache. */ 158 XML_ENTITY_TEMP; 159 } 160 161 /** The concurrency level for the guava caches. */ 162 static final int CONCURRENCY_LEVEL = 8; 163 164 /** Set interval for clearing the caches to 10 minutes. */ 165 private static final int INTERVAL_CLEAR = 1000 * 60 * 10; 166 167 /** The log object for this class. */ 168 private static final Log LOG = CmsLog.getLog(CmsMemoryMonitor.class); 169 170 /** Flag indicating if monitor is currently running. */ 171 private static boolean m_currentlyRunning; 172 173 /** Maximum depth for object size recursion. */ 174 private static final int MAX_DEPTH = 5; 175 176 /** Cache for access control lists. */ 177 private Map<String, CmsAccessControlList> m_cacheAccessControlList; 178 179 /** A temporary cache for XML content definitions. */ 180 private Map<String, CmsXmlContentDefinition> m_cacheContentDefinitions; 181 182 /** Cache for groups. */ 183 private Map<String, CmsGroup> m_cacheGroup; 184 185 /** Cache for roles. */ 186 private Map<String, Boolean> m_cacheHasRoles; 187 188 /** A cache for accelerated locale lookup. */ 189 private Map<String, Locale> m_cacheLocale; 190 191 /** Cache for the resource locks. */ 192 private Map<String, CmsLock> m_cacheLock; 193 194 /** The memory object cache map. */ 195 private Map<String, Object> m_cacheMemObject; 196 197 /** Cache for organizational units. */ 198 private Map<String, CmsOrganizationalUnit> m_cacheOrgUnit; 199 200 /** Cache for permission checks. */ 201 private Map<String, I_CmsPermissionHandler.CmsPermissionCheckResult> m_cachePermission; 202 203 /** Cache for offline projects. */ 204 private Map<String, CmsProject> m_cacheProject; 205 206 /** Cache for project resources. */ 207 private Map<String, List<CmsResource>> m_cacheProjectResources; 208 209 /** Cache for properties. */ 210 private Map<String, CmsProperty> m_cacheProperty; 211 212 /** Cache for property lists. */ 213 private Map<String, List<CmsProperty>> m_cachePropertyList; 214 215 /** Cache for published resources. */ 216 private Map<String, List<CmsPublishedResource>> m_cachePublishedResources; 217 218 /** Cache for resources. */ 219 private Map<String, CmsResource> m_cacheResource; 220 221 /** Cache for resource lists. */ 222 private Map<String, List<CmsResource>> m_cacheResourceList; 223 224 /** Cache for role lists. */ 225 private Map<String, List<CmsRole>> m_cacheRoleLists; 226 227 /** Cache for user data. */ 228 private Map<String, CmsUser> m_cacheUser; 229 230 /** Cache for user groups. */ 231 private CmsGroupListCache m_cacheUserGroups; 232 233 /** Cache for user lists. */ 234 private Map<String, List<CmsUser>> m_cacheUserList; 235 236 /** The vfs memory cache map. */ 237 private Map<String, Object> m_cacheVfsObject; 238 239 /** A permanent cache to avoid multiple readings of often used files from the VFS. */ 240 private Map<String, byte[]> m_cacheXmlPermanentEntity; 241 242 /** A temporary cache to avoid multiple readings of often used files from the VFS. */ 243 private Map<String, byte[]> m_cacheXmlTemporaryEntity; 244 245 /** The memory monitor configuration. */ 246 private CmsMemoryMonitorConfiguration m_configuration; 247 248 /** Map to keep track of disabled caches. */ 249 private Map<CacheType, Boolean> m_disabled = new HashMap<CacheType, Boolean>(); 250 251 /** Interval in which emails are send. */ 252 private int m_intervalEmail; 253 254 /** Interval in which the log is written. */ 255 private int m_intervalLog; 256 257 /** Interval between 2 warnings. */ 258 private int m_intervalWarning; 259 260 /** The time the caches were last cleared. */ 261 private long m_lastClearCache; 262 263 /** The time the last status email was send. */ 264 private long m_lastEmailStatus; 265 266 /** The time the last warning email was send. */ 267 private long m_lastEmailWarning; 268 269 /** The time the last status log was written. */ 270 private long m_lastLogStatus; 271 272 /** The time the last warning log was written. */ 273 private long m_lastLogWarning; 274 275 /** The number of times the log entry was written. */ 276 private int m_logCount; 277 278 /** Memory percentage to reach to go to warning level. */ 279 private int m_maxUsagePercent; 280 281 /** The average memory status. */ 282 private CmsMemoryStatus m_memoryAverage; 283 284 /** The current memory status. */ 285 private CmsMemoryStatus m_memoryCurrent; 286 287 /** Contains the object to be monitored. */ 288 private Map<String, Object> m_monitoredObjects; 289 290 /** Buffer for publish history. */ 291 private Buffer m_publishHistory; 292 293 /** Buffer for publish jobs. */ 294 private Buffer m_publishQueue; 295 296 /** Cache for resource OU data. */ 297 private LoadingCache<ResourceOUCacheKey, ResourceOUMap> m_resourceOuCache; 298 299 /** Flag for memory warning mail send. */ 300 private boolean m_warningLoggedSinceLastStatus; 301 302 /** Flag for memory warning mail send. */ 303 private boolean m_warningSendSinceLastStatus; 304 305 /** 306 * Empty constructor, required by OpenCms scheduler.<p> 307 */ 308 public CmsMemoryMonitor() { 309 310 m_monitoredObjects = new HashMap<String, Object>(); 311 LoadingCache<ResourceOUCacheKey, ResourceOUMap> resourceOUCache = CacheBuilder.newBuilder().expireAfterWrite( 312 60, 313 TimeUnit.SECONDS).build(new CacheLoader<ResourceOUCacheKey, ResourceOUMap>() { 314 315 @Override 316 public ResourceOUMap load(ResourceOUCacheKey key) throws Exception { 317 318 ResourceOUMap result = new CmsDriverManager.ResourceOUMap(); 319 result.init(key.getDriverManager(), key.getDbContext()); 320 return result; 321 } 322 }); 323 m_resourceOuCache = resourceOUCache; 324 } 325 326 /** 327 * Creates a thread safe LRU cache map based on the guava cache builder.<p> 328 * Use this instead of synchronized maps for better performance.<p> 329 * 330 * @param capacity the cache capacity 331 * 332 * @return the cache map 333 */ 334 @SuppressWarnings("unchecked") 335 public static <T, V> Map<T, V> createLRUCacheMap(int capacity) { 336 337 CacheBuilder<?, ?> builder = CacheBuilder.newBuilder().concurrencyLevel(CONCURRENCY_LEVEL).maximumSize( 338 capacity); 339 return (Map<T, V>)(builder.build().asMap()); 340 } 341 342 /** 343 * Returns the size of objects that are instances of 344 * <code>byte[]</code>, <code>String</code>, <code>CmsFile</code>,<code>I_CmsLruCacheObject</code>.<p> 345 * For other objects, a size of 0 is returned. 346 * 347 * @param obj the object 348 * @return the size of the object 349 */ 350 public static int getMemorySize(Object obj) { 351 352 if (obj instanceof I_CmsMemoryMonitorable) { 353 return ((I_CmsMemoryMonitorable)obj).getMemorySize(); 354 } 355 356 if (obj instanceof byte[]) { 357 // will always be a total of 16 + 8 358 return 8 + (int)(Math.ceil(((byte[])obj).length / 16.0) * 16.0); 359 } 360 361 if (obj instanceof String) { 362 // will always be a total of 16 + 24 363 return 24 + (int)(Math.ceil(((String)obj).length() / 8.0) * 16.0); 364 } 365 366 if (obj instanceof CmsFile) { 367 CmsFile f = (CmsFile)obj; 368 if (f.getContents() != null) { 369 return f.getContents().length + 1024; 370 } else { 371 return 1024; 372 } 373 } 374 375 if (obj instanceof CmsUUID) { 376 return 184; // worst case if UUID String has been generated 377 } 378 379 if (obj instanceof CmsPermissionSet) { 380 return 16; // two ints 381 } 382 383 if (obj instanceof CmsResource) { 384 return 1024; // estimated size 385 } 386 387 if (obj instanceof CmsPublishedResource) { 388 return 512; // estimated size 389 } 390 391 if (obj instanceof CmsUser) { 392 return 2048; // estimated size 393 } 394 395 if (obj instanceof CmsGroup) { 396 return 512; // estimated size 397 } 398 399 if (obj instanceof CmsProject) { 400 return 512; // estimated size 401 } 402 403 if (obj instanceof Boolean) { 404 return 8; // one boolean 405 } 406 407 if (obj instanceof CmsProperty) { 408 int size = 8; 409 410 CmsProperty property = (CmsProperty)obj; 411 size += getMemorySize(property.getName()); 412 413 if (property.getResourceValue() != null) { 414 size += getMemorySize(property.getResourceValue()); 415 } 416 417 if (property.getStructureValue() != null) { 418 size += getMemorySize(property.getStructureValue()); 419 } 420 421 if (property.getOrigin() != null) { 422 size += getMemorySize(property.getOrigin()); 423 } 424 425 return size; 426 } 427 428 if (obj instanceof CmsPropertyDefinition) { 429 int size = 8; 430 431 CmsPropertyDefinition propDef = (CmsPropertyDefinition)obj; 432 size += getMemorySize(propDef.getName()); 433 size += getMemorySize(propDef.getId()); 434 435 return size; 436 } 437 438 return 8; 439 } 440 441 /** 442 * Returns the total value size of a list object.<p> 443 * 444 * @param listValue the list object 445 * @param depth the max recursion depth for calculation the size 446 * 447 * @return the size of the list object 448 */ 449 public static long getValueSize(List<?> listValue, int depth) { 450 451 long totalSize = 0; 452 try { 453 Object[] values = listValue.toArray(); 454 for (int i = 0, s = values.length; i < s; i++) { 455 456 Object obj = values[i]; 457 458 if (obj instanceof CmsAccessControlList) { 459 obj = ((CmsAccessControlList)obj).getPermissionMap(); 460 } 461 462 if (obj instanceof CmsFlexCacheVariation) { 463 obj = ((CmsFlexCacheVariation)obj).m_map; 464 } 465 466 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 467 totalSize += getValueSize((Map<?, ?>)obj, depth + 1); 468 continue; 469 } 470 471 if ((obj instanceof List) && (depth < MAX_DEPTH)) { 472 totalSize += getValueSize((List<?>)obj, depth + 1); 473 continue; 474 } 475 476 totalSize += getMemorySize(obj); 477 } 478 } catch (ConcurrentModificationException e) { 479 // this might happen since even the .toArray() method internally creates an iterator 480 } catch (Throwable t) { 481 // catch all other exceptions otherwise the whole monitor will stop working 482 if (LOG.isDebugEnabled()) { 483 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 484 } 485 } 486 487 return totalSize; 488 } 489 490 /** 491 * Returns the total value size of a map object.<p> 492 * 493 * @param mapValue the map object 494 * @param depth the max recursion depth for calculation the size 495 * 496 * @return the size of the map object 497 */ 498 public static long getValueSize(Map<?, ?> mapValue, int depth) { 499 500 long totalSize = 0; 501 try { 502 Object[] values = mapValue.values().toArray(); 503 for (int i = 0, s = values.length; i < s; i++) { 504 505 Object obj = values[i]; 506 507 if (obj instanceof CmsAccessControlList) { 508 obj = ((CmsAccessControlList)obj).getPermissionMap(); 509 } 510 511 if (obj instanceof CmsFlexCacheVariation) { 512 obj = ((CmsFlexCacheVariation)obj).m_map; 513 } 514 515 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 516 totalSize += getValueSize((Map<?, ?>)obj, depth + 1); 517 continue; 518 } 519 520 if ((obj instanceof List) && (depth < MAX_DEPTH)) { 521 totalSize += getValueSize((List<?>)obj, depth + 1); 522 continue; 523 } 524 525 totalSize += getMemorySize(obj); 526 } 527 } catch (ConcurrentModificationException e) { 528 // this might happen since even the .toArray() method internally creates an iterator 529 } catch (Throwable t) { 530 // catch all other exceptions otherwise the whole monitor will stop working 531 if (LOG.isDebugEnabled()) { 532 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 533 } 534 } 535 536 return totalSize; 537 } 538 539 /** 540 * Returns the value sizes of value objects within the monitored object.<p> 541 * 542 * @param obj the object 543 * 544 * @return the value sizes of value objects or "-"-fields 545 */ 546 public static long getValueSize(Object obj) { 547 548 if (obj instanceof CmsLruCache) { 549 return ((CmsLruCache)obj).size(); 550 } 551 552 if (obj instanceof Map) { 553 return getValueSize((Map<?, ?>)obj, 1); 554 } 555 556 if (obj instanceof List) { 557 return getValueSize((List<?>)obj, 1); 558 } 559 560 try { 561 return getMemorySize(obj); 562 } catch (Exception exc) { 563 return 0; 564 } 565 } 566 567 /** 568 * Caches the given acl under the given cache key.<p> 569 * 570 * @param key the cache key 571 * @param acl the acl to cache 572 */ 573 public void cacheACL(String key, CmsAccessControlList acl) { 574 575 if (m_disabled.get(CacheType.ACL) != null) { 576 return; 577 } 578 m_cacheAccessControlList.put(key, acl); 579 } 580 581 /** 582 * Caches the given content definition under the given cache key.<p> 583 * 584 * @param key the cache key 585 * @param contentDefinition the content definition to cache 586 */ 587 public void cacheContentDefinition(String key, CmsXmlContentDefinition contentDefinition) { 588 589 if (m_disabled.get(CacheType.CONTENT_DEFINITION) != null) { 590 return; 591 } 592 m_cacheContentDefinitions.put(key, contentDefinition); 593 } 594 595 /** 596 * Caches the given group under its id AND fully qualified name.<p> 597 * 598 * @param group the group to cache 599 */ 600 public void cacheGroup(CmsGroup group) { 601 602 if (m_disabled.get(CacheType.GROUP) != null) { 603 return; 604 } 605 m_cacheGroup.put(group.getId().toString(), group); 606 m_cacheGroup.put(group.getName(), group); 607 } 608 609 /** 610 * Caches the given locale under the given cache key.<p> 611 * 612 * @param key the cache key 613 * @param locale the locale to cache 614 */ 615 public void cacheLocale(String key, Locale locale) { 616 617 if (m_cacheLocale != null) { 618 if (m_disabled.get(CacheType.LOCALE) != null) { 619 return; 620 } 621 // this may be accessed before initialization 622 m_cacheLocale.put(key, locale); 623 } 624 } 625 626 /** 627 * Caches the given lock.<p> 628 * 629 * The lock is cached by it resource's root path.<p> 630 * 631 * @param lock the lock to cache 632 */ 633 public void cacheLock(CmsLock lock) { 634 635 if (m_disabled.get(CacheType.LOCK) != null) { 636 return; 637 } 638 m_cacheLock.put(lock.getResourceName(), lock); 639 } 640 641 /** 642 * Caches the given object under the given cache key.<p> 643 * 644 * @param key the cache key 645 * @param obj the object to cache 646 */ 647 public void cacheMemObject(String key, Object obj) { 648 649 if (m_disabled.get(CacheType.MEMORY_OBJECT) != null) { 650 return; 651 } 652 m_cacheMemObject.put(key, obj); 653 } 654 655 /** 656 * Caches the given organizational under its id AND the fully qualified name.<p> 657 * 658 * @param orgUnit the organizational unit to cache 659 */ 660 public void cacheOrgUnit(CmsOrganizationalUnit orgUnit) { 661 662 if (m_disabled.get(CacheType.ORG_UNIT) != null) { 663 return; 664 } 665 m_cacheOrgUnit.put(orgUnit.getId().toString(), orgUnit); 666 m_cacheOrgUnit.put(orgUnit.getName(), orgUnit); 667 } 668 669 /** 670 * Caches the given permission check result under the given cache key.<p> 671 * 672 * @param key the cache key 673 * @param permission the permission check result to cache 674 */ 675 public void cachePermission(String key, I_CmsPermissionHandler.CmsPermissionCheckResult permission) { 676 677 if (m_disabled.get(CacheType.PERMISSION) != null) { 678 return; 679 } 680 m_cachePermission.put(key, permission); 681 } 682 683 /** 684 * Caches the given project under its id AND the fully qualified name.<p> 685 * 686 * @param project the project to cache 687 */ 688 public void cacheProject(CmsProject project) { 689 690 if (m_disabled.get(CacheType.PROJECT) != null) { 691 return; 692 } 693 m_cacheProject.put(project.getUuid().toString(), project); 694 m_cacheProject.put(project.getName(), project); 695 } 696 697 /** 698 * Caches the given project resource list under the given cache key.<p> 699 * 700 * @param key the cache key 701 * @param projectResources the project resources to cache 702 */ 703 public void cacheProjectResources(String key, List<CmsResource> projectResources) { 704 705 if (m_disabled.get(CacheType.PROJECT_RESOURCES) != null) { 706 return; 707 } 708 m_cacheProjectResources.put(key, projectResources); 709 } 710 711 /** 712 * Caches the given property under the given cache key.<p> 713 * 714 * @param key the cache key 715 * @param property the property to cache 716 */ 717 public void cacheProperty(String key, CmsProperty property) { 718 719 if (m_disabled.get(CacheType.PROPERTY) != null) { 720 return; 721 } 722 m_cacheProperty.put(key, property); 723 } 724 725 /** 726 * Caches the given property list under the given cache key.<p> 727 * 728 * @param key the cache key 729 * @param propertyList the property list to cache 730 */ 731 public void cachePropertyList(String key, List<CmsProperty> propertyList) { 732 733 if (m_disabled.get(CacheType.PROPERTY_LIST) != null) { 734 return; 735 } 736 m_cachePropertyList.put(key, propertyList); 737 } 738 739 /** 740 * Caches the given published resources list under the given cache key.<p> 741 * 742 * @param cacheKey the cache key 743 * @param publishedResources the published resources list to cache 744 */ 745 public void cachePublishedResources(String cacheKey, List<CmsPublishedResource> publishedResources) { 746 747 if (m_disabled.get(CacheType.PUBLISHED_RESOURCES) != null) { 748 return; 749 } 750 if (publishedResources == null) { 751 m_cachePublishedResources.remove(cacheKey); 752 } else { 753 m_cachePublishedResources.put(cacheKey, publishedResources); 754 } 755 } 756 757 /** 758 * Caches the given publish job.<p> 759 * 760 * @param publishJob the publish job 761 */ 762 @SuppressWarnings("unchecked") 763 public void cachePublishJob(CmsPublishJobInfoBean publishJob) { 764 765 if (m_disabled.get(CacheType.PUBLISH_QUEUE) != null) { 766 return; 767 } 768 m_publishQueue.add(publishJob); 769 } 770 771 /** 772 * Caches the given publish job in the publish job history.<p> 773 * 774 * @param publishJob the publish job 775 */ 776 @SuppressWarnings("unchecked") 777 public void cachePublishJobInHistory(CmsPublishJobInfoBean publishJob) { 778 779 if (m_disabled.get(CacheType.PUBLISH_HISTORY) != null) { 780 return; 781 } 782 m_publishHistory.add(publishJob); 783 } 784 785 /** 786 * Caches the given resource under the given cache key.<p> 787 * 788 * @param key the cache key 789 * @param resource the resource to cache 790 */ 791 public void cacheResource(String key, CmsResource resource) { 792 793 if (m_disabled.get(CacheType.RESOURCE) != null) { 794 return; 795 } 796 m_cacheResource.put(key, resource); 797 } 798 799 /** 800 * Caches the given resource list under the given cache key.<p> 801 * 802 * @param key the cache key 803 * @param resourceList the resource list to cache 804 */ 805 public void cacheResourceList(String key, List<CmsResource> resourceList) { 806 807 if (m_disabled.get(CacheType.RESOURCE_LIST) != null) { 808 return; 809 } 810 if ((resourceList instanceof CmsDriverManager.ResourceListWithCacheability) 811 && !((CmsDriverManager.ResourceListWithCacheability)resourceList).isCacheable()) { 812 return; 813 } 814 m_cacheResourceList.put(key, resourceList); 815 } 816 817 /** 818 * Caches the given value under the given cache key.<p> 819 * 820 * @param key the cache key 821 * @param hasRole if the user has the given role 822 */ 823 public void cacheRole(String key, boolean hasRole) { 824 825 if (m_disabled.get(CacheType.HAS_ROLE) != null) { 826 return; 827 } 828 m_cacheHasRoles.put(key, Boolean.valueOf(hasRole)); 829 } 830 831 /** 832 * Caches the given value under the given cache key.<p> 833 * 834 * @param key the cache key 835 * @param roles the roles of the user 836 */ 837 public void cacheRoleList(String key, List<CmsRole> roles) { 838 839 if (m_disabled.get(CacheType.ROLE_LIST) != null) { 840 return; 841 } 842 m_cacheRoleLists.put(key, roles); 843 } 844 845 /** 846 * Caches the given user under its id AND the fully qualified name.<p> 847 * 848 * @param user the user to cache 849 */ 850 public void cacheUser(CmsUser user) { 851 852 if (m_disabled.get(CacheType.USER) != null) { 853 return; 854 } 855 m_cacheUser.put(user.getId().toString(), user); 856 m_cacheUser.put(user.getName(), user); 857 } 858 859 /** 860 * Caches the given list of users under the given cache key.<p> 861 * 862 * @param key the cache key 863 * @param userList the list of users to cache 864 */ 865 public void cacheUserList(String key, List<CmsUser> userList) { 866 867 if (m_disabled.get(CacheType.USER_LIST) != null) { 868 return; 869 } 870 m_cacheUserList.put(key, userList); 871 } 872 873 /** 874 * Caches the given vfs object under the given cache key.<p> 875 * 876 * @param key the cache key 877 * @param obj the vfs object to cache 878 */ 879 public void cacheVfsObject(String key, Object obj) { 880 881 if (m_disabled.get(CacheType.VFS_OBJECT) != null) { 882 return; 883 } 884 m_cacheVfsObject.put(key, obj); 885 } 886 887 /** 888 * Caches the given xml entity under the given system id.<p> 889 * 890 * @param systemId the cache key 891 * @param content the content to cache 892 */ 893 public void cacheXmlPermanentEntity(String systemId, byte[] content) { 894 895 if (m_disabled.get(CacheType.XML_ENTITY_PERM) != null) { 896 return; 897 } 898 m_cacheXmlPermanentEntity.put(systemId, content); 899 } 900 901 /** 902 * Caches the given xml entity under the given cache key.<p> 903 * 904 * @param key the cache key 905 * @param content the content to cache 906 */ 907 public void cacheXmlTemporaryEntity(String key, byte[] content) { 908 909 if (m_disabled.get(CacheType.XML_ENTITY_TEMP) != null) { 910 return; 911 } 912 m_cacheXmlTemporaryEntity.put(key, content); 913 } 914 915 /** 916 * Clears the access control list cache when access control entries are changed.<p> 917 */ 918 public void clearAccessControlListCache() { 919 920 flushCache(CacheType.ACL); 921 flushCache(CacheType.PERMISSION); 922 clearResourceCache(); 923 } 924 925 /** 926 * Clears almost all internal caches.<p> 927 */ 928 public void clearCache() { 929 930 clearPrincipalsCache(); 931 932 flushCache(CacheType.PROJECT); 933 flushCache(CacheType.RESOURCE); 934 flushCache(CacheType.RESOURCE_LIST); 935 flushCache(CacheType.PROPERTY); 936 flushCache(CacheType.PROPERTY_LIST); 937 flushCache(CacheType.PROJECT_RESOURCES); 938 flushCache(CacheType.PUBLISHED_RESOURCES); 939 } 940 941 /** 942 * Clears the caches for publishing. 943 */ 944 public void clearCacheForPublishing() { 945 946 flushCache(CacheType.USER); 947 flushCache(CacheType.GROUP); 948 flushCache(CacheType.ORG_UNIT); 949 flushCache(CacheType.ACL); 950 flushCache(CacheType.PERMISSION); 951 flushCache(CacheType.HAS_ROLE); 952 flushCache(CacheType.ROLE_LIST); 953 flushCache(CacheType.USER_LIST); 954 flushCache(CacheType.PROJECT); 955 flushCache(CacheType.RESOURCE); 956 flushCache(CacheType.RESOURCE_LIST); 957 flushCache(CacheType.PROPERTY); 958 flushCache(CacheType.PROPERTY_LIST); 959 flushCache(CacheType.PROJECT_RESOURCES); 960 flushCache(CacheType.PUBLISHED_RESOURCES); 961 962 } 963 964 /** 965 * Clears all internal principal-related caches.<p> 966 */ 967 public void clearPrincipalsCache() { 968 969 flushCache(CacheType.USER); 970 flushCache(CacheType.GROUP); 971 flushCache(CacheType.ORG_UNIT); 972 flushCache(CacheType.ACL); 973 flushCache(CacheType.PERMISSION); 974 flushCache(CacheType.HAS_ROLE); 975 flushCache(CacheType.ROLE_LIST); 976 flushCache(CacheType.USERGROUPS); 977 flushCache(CacheType.USER_LIST); 978 } 979 980 /** 981 * Clears all the depending caches when a resource was changed.<p> 982 */ 983 public void clearResourceCache() { 984 985 flushCache(CacheType.RESOURCE); 986 flushCache(CacheType.RESOURCE_LIST); 987 flushCache(CacheType.HAS_ROLE); 988 flushCache(CacheType.ROLE_LIST); 989 } 990 991 /** 992 * Clears the user cache for the given user.<p> 993 * 994 * @param user the user 995 */ 996 public void clearUserCache(CmsUser user) { 997 998 uncacheUser(user); 999 flushCache(CacheType.RESOURCE_LIST); 1000 } 1001 1002 /** 1003 * Disables the given cache.<p> 1004 * 1005 * @param types the cache type to disable 1006 */ 1007 public void disableCache(CacheType... types) { 1008 1009 for (CacheType type : types) { 1010 m_disabled.put(type, Boolean.TRUE); 1011 } 1012 flushCache(types); 1013 } 1014 1015 /** 1016 * Enables the given cache.<p> 1017 * 1018 * @param types the cache type to disable 1019 */ 1020 public void enableCache(CacheType... types) { 1021 1022 for (CacheType type : types) { 1023 m_disabled.remove(type); 1024 } 1025 } 1026 1027 /** 1028 * Returns if monitoring is enabled.<p> 1029 * 1030 * @return true if monitoring is enabled 1031 */ 1032 public boolean enabled() { 1033 1034 return true; 1035 } 1036 1037 /** 1038 * Flushes the ACL cache.<p> 1039 * 1040 * @deprecated use {@link #flushCache(CacheType[])} instead 1041 */ 1042 @Deprecated 1043 public void flushACLs() { 1044 1045 flushCache(CacheType.ACL); 1046 } 1047 1048 /** 1049 * Flushes the given cache.<p> 1050 * 1051 * @param types the cache types to flush 1052 */ 1053 public void flushCache(CacheType... types) { 1054 1055 for (CacheType type : types) { 1056 switch (type) { 1057 case ACL: 1058 m_cacheAccessControlList.clear(); 1059 break; 1060 case CONTENT_DEFINITION: 1061 m_cacheContentDefinitions.clear(); 1062 break; 1063 case GROUP: 1064 m_cacheGroup.clear(); 1065 break; 1066 case HAS_ROLE: 1067 m_cacheHasRoles.clear(); 1068 break; 1069 case LOCALE: 1070 m_cacheLocale.clear(); 1071 break; 1072 case LOCK: 1073 m_cacheLock.clear(); 1074 break; 1075 case MEMORY_OBJECT: 1076 m_cacheMemObject.clear(); 1077 break; 1078 case ORG_UNIT: 1079 m_cacheOrgUnit.clear(); 1080 break; 1081 case PERMISSION: 1082 m_cachePermission.clear(); 1083 break; 1084 case PROJECT: 1085 m_cacheProject.clear(); 1086 break; 1087 case PROJECT_RESOURCES: 1088 m_cacheProjectResources.clear(); 1089 break; 1090 case PROPERTY: 1091 m_cacheProperty.clear(); 1092 break; 1093 case PROPERTY_LIST: 1094 m_cachePropertyList.clear(); 1095 break; 1096 case PUBLISHED_RESOURCES: 1097 m_cachePublishedResources.clear(); 1098 break; 1099 case PUBLISH_HISTORY: 1100 m_publishHistory.clear(); 1101 break; 1102 case PUBLISH_QUEUE: 1103 m_publishQueue.clear(); 1104 break; 1105 case RESOURCE: 1106 m_cacheResource.clear(); 1107 break; 1108 case RESOURCE_LIST: 1109 m_cacheResourceList.clear(); 1110 break; 1111 case ROLE_LIST: 1112 m_cacheRoleLists.clear(); 1113 m_resourceOuCache.invalidateAll(); 1114 break; 1115 case USER: 1116 m_cacheUser.clear(); 1117 break; 1118 case USERGROUPS: 1119 m_cacheUserGroups.clear(); 1120 break; 1121 case USER_LIST: 1122 m_cacheUserList.clear(); 1123 break; 1124 case VFS_OBJECT: 1125 m_cacheVfsObject.clear(); 1126 break; 1127 case XML_ENTITY_PERM: 1128 m_cacheXmlPermanentEntity.clear(); 1129 break; 1130 case XML_ENTITY_TEMP: 1131 m_cacheXmlTemporaryEntity.clear(); 1132 break; 1133 default: 1134 // can't happen 1135 } 1136 } 1137 } 1138 1139 /** 1140 * Flushes the xml content definitions cache.<p> 1141 * 1142 * @deprecated use {@link #flushCache(CacheType[])} instead 1143 */ 1144 @Deprecated 1145 public void flushContentDefinitions() { 1146 1147 flushCache(CacheType.CONTENT_DEFINITION); 1148 } 1149 1150 /** 1151 * Flushes the group cache.<p> 1152 * 1153 * @deprecated use {@link #flushCache(CacheType[])} instead 1154 */ 1155 @Deprecated 1156 public void flushGroups() { 1157 1158 flushCache(CacheType.GROUP); 1159 } 1160 1161 /** 1162 * Flushes the locale cache.<p> 1163 * 1164 * @deprecated use {@link #flushCache(CacheType[])} instead 1165 */ 1166 @Deprecated 1167 public void flushLocales() { 1168 1169 flushCache(CacheType.LOCALE); 1170 } 1171 1172 /** 1173 * Flushes the locks cache.<p> 1174 * 1175 * @param newLocks if not <code>null</code> the lock cache is replaced by the given map 1176 */ 1177 public void flushLocks(Map<String, CmsLock> newLocks) { 1178 1179 if ((newLocks == null) || newLocks.isEmpty()) { 1180 flushCache(CacheType.LOCK); 1181 return; 1182 } 1183 // initialize new lock cache 1184 Map<String, CmsLock> newLockCache = new ConcurrentHashMap<String, CmsLock>(newLocks); 1185 // register it 1186 register(CmsLockManager.class.getName(), newLockCache); 1187 // save the old cache 1188 Map<String, CmsLock> oldCache = m_cacheLock; 1189 // replace the old by the new cache 1190 m_cacheLock = newLockCache; 1191 // clean up the old cache 1192 oldCache.clear(); 1193 } 1194 1195 /** 1196 * Flushes the memory object cache.<p> 1197 * 1198 * @deprecated use {@link #flushCache(CacheType[])} instead 1199 */ 1200 @Deprecated 1201 public void flushMemObjects() { 1202 1203 flushCache(CacheType.MEMORY_OBJECT); 1204 } 1205 1206 /** 1207 * Flushes the organizational unit cache.<p> 1208 * 1209 * @deprecated use {@link #flushCache(CacheType[])} instead 1210 */ 1211 @Deprecated 1212 public void flushOrgUnits() { 1213 1214 flushCache(CacheType.ORG_UNIT); 1215 } 1216 1217 /** 1218 * Flushes the permission check result cache.<p> 1219 * 1220 * @deprecated use {@link #flushCache(CacheType[])} instead 1221 */ 1222 @Deprecated 1223 public void flushPermissions() { 1224 1225 flushCache(CacheType.PERMISSION); 1226 } 1227 1228 /** 1229 * Flushes the project resources cache.<p> 1230 * 1231 * @deprecated use {@link #flushCache(CacheType[])} instead 1232 */ 1233 @Deprecated 1234 public void flushProjectResources() { 1235 1236 flushCache(CacheType.PROJECT_RESOURCES); 1237 } 1238 1239 /** 1240 * Flushes the project cache.<p> 1241 * 1242 * @deprecated use {@link #flushCache(CacheType[])} instead 1243 */ 1244 @Deprecated 1245 public void flushProjects() { 1246 1247 flushCache(CacheType.PROJECT); 1248 } 1249 1250 /** 1251 * Flushes the property cache.<p> 1252 * 1253 * @deprecated use {@link #flushCache(CacheType[])} instead 1254 */ 1255 @Deprecated 1256 public void flushProperties() { 1257 1258 flushCache(CacheType.PROPERTY); 1259 } 1260 1261 /** 1262 * Flushes the property list cache.<p> 1263 * 1264 * @deprecated use {@link #flushCache(CacheType[])} instead 1265 */ 1266 @Deprecated 1267 public void flushPropertyLists() { 1268 1269 flushCache(CacheType.PROPERTY_LIST); 1270 } 1271 1272 /** 1273 * Flushes the published resources cache.<p> 1274 * 1275 * @deprecated use {@link #flushCache(CacheType[])} instead 1276 */ 1277 @Deprecated 1278 public void flushPublishedResources() { 1279 1280 flushCache(CacheType.PUBLISHED_RESOURCES); 1281 } 1282 1283 /** 1284 * Flushes the publish history.<p> 1285 * 1286 * @deprecated use {@link #flushCache(CacheType[])} instead 1287 */ 1288 @Deprecated 1289 public void flushPublishJobHistory() { 1290 1291 flushCache(CacheType.PUBLISH_HISTORY); 1292 } 1293 1294 /** 1295 * Flushes the publish queue.<p> 1296 * 1297 * @deprecated use {@link #flushCache(CacheType[])} instead 1298 */ 1299 @Deprecated 1300 public void flushPublishJobs() { 1301 1302 flushCache(CacheType.PUBLISH_QUEUE); 1303 } 1304 1305 /** 1306 * Flushes the resource list cache.<p> 1307 * 1308 * @deprecated use {@link #flushCache(CacheType[])} instead 1309 */ 1310 @Deprecated 1311 public void flushResourceLists() { 1312 1313 flushCache(CacheType.RESOURCE_LIST); 1314 } 1315 1316 /** 1317 * Flushes the resource cache.<p> 1318 * 1319 * @deprecated use {@link #flushCache(CacheType[])} instead 1320 */ 1321 @Deprecated 1322 public void flushResources() { 1323 1324 flushCache(CacheType.RESOURCE); 1325 } 1326 1327 /** 1328 * Flushes the role lists cache.<p> 1329 * 1330 * @deprecated use {@link #flushCache(CacheType[])} instead 1331 */ 1332 @Deprecated 1333 public void flushRoleLists() { 1334 1335 flushCache(CacheType.ROLE_LIST); 1336 } 1337 1338 /** 1339 * Flushes the roles cache.<p> 1340 * 1341 * @deprecated use {@link #flushCache(CacheType[])} instead 1342 */ 1343 @Deprecated 1344 public void flushRoles() { 1345 1346 flushCache(CacheType.HAS_ROLE); 1347 } 1348 1349 /** 1350 * Flushes the user groups cache.<p> 1351 * 1352 * @deprecated use {@link #flushCache(CacheType[])} instead 1353 */ 1354 @Deprecated 1355 public void flushUserGroups() { 1356 1357 flushCache(CacheType.USERGROUPS); 1358 flushCache(CacheType.USER_LIST); 1359 } 1360 1361 /** 1362 * Flushes the user group cache for the user with the given id. 1363 * 1364 * @param id the user id 1365 **/ 1366 public void flushUserGroups(CmsUUID id) { 1367 1368 m_cacheUserGroups.clearUser(id); 1369 } 1370 1371 /** 1372 * Flushes the users cache.<p> 1373 * 1374 * @deprecated use {@link #flushCache(CacheType[])} instead 1375 */ 1376 @Deprecated 1377 public void flushUsers() { 1378 1379 flushCache(CacheType.USER); 1380 } 1381 1382 /** 1383 * Flushes the vfs object cache.<p> 1384 * 1385 * @deprecated use {@link #flushCache(CacheType[])} instead 1386 */ 1387 @Deprecated 1388 public void flushVfsObjects() { 1389 1390 flushCache(CacheType.VFS_OBJECT); 1391 } 1392 1393 /** 1394 * Flushes the xml permanent entities cache.<p> 1395 * 1396 * @deprecated use {@link #flushCache(CacheType[])} instead 1397 */ 1398 @Deprecated 1399 public void flushXmlPermanentEntities() { 1400 1401 flushCache(CacheType.XML_ENTITY_PERM); 1402 } 1403 1404 /** 1405 * Flushes the xml temporary entities cache.<p> 1406 * 1407 * @deprecated use {@link #flushCache(CacheType[])} instead 1408 */ 1409 @Deprecated 1410 public void flushXmlTemporaryEntities() { 1411 1412 flushCache(CacheType.XML_ENTITY_TEMP); 1413 } 1414 1415 /** 1416 * Returns all cached lock root paths.<p> 1417 * 1418 * @return a list of {@link String} objects 1419 */ 1420 public List<String> getAllCachedLockPaths() { 1421 1422 return new ArrayList<String>(m_cacheLock.keySet()); 1423 } 1424 1425 /** 1426 * Returns all cached locks.<p> 1427 * 1428 * @return a list of {@link CmsLock} objects 1429 */ 1430 public List<CmsLock> getAllCachedLocks() { 1431 1432 return new ArrayList<CmsLock>(m_cacheLock.values()); 1433 } 1434 1435 /** 1436 * Returns all cached publish jobs in the queue as ordered list.<p> 1437 * 1438 * @return all cached publish jobs 1439 */ 1440 @SuppressWarnings("unchecked") 1441 public List<CmsPublishJobInfoBean> getAllCachedPublishJobs() { 1442 1443 return new ArrayList<CmsPublishJobInfoBean>(m_publishQueue); 1444 } 1445 1446 /** 1447 * Returns all cached publish jobs in the history as ordered list.<p> 1448 * 1449 * @return all cached publish jobs 1450 */ 1451 @SuppressWarnings("unchecked") 1452 public List<CmsPublishJobInfoBean> getAllCachedPublishJobsInHistory() { 1453 1454 return new ArrayList<CmsPublishJobInfoBean>(m_publishHistory); 1455 } 1456 1457 /** 1458 * Returns the ACL cached with the given cache key or <code>null</code> if not found.<p> 1459 * 1460 * @param key the cache key to look for 1461 * 1462 * @return the ACL cached with the given cache key 1463 */ 1464 public CmsAccessControlList getCachedACL(String key) { 1465 1466 return m_cacheAccessControlList.get(key); 1467 } 1468 1469 /** 1470 * Returns the xml content definition cached with the given cache key or <code>null</code> if not found.<p> 1471 * 1472 * @param key the cache key to look for 1473 * 1474 * @return the xml content definition cached with the given cache key 1475 */ 1476 public CmsXmlContentDefinition getCachedContentDefinition(String key) { 1477 1478 return m_cacheContentDefinitions.get(key); 1479 } 1480 1481 /** 1482 * Returns the group cached with the given cache key or <code>null</code> if not found.<p> 1483 * 1484 * @param key the cache key to look for, this may be the group's uuid or the fqn 1485 * 1486 * @return the group cached with the given cache key 1487 */ 1488 public CmsGroup getCachedGroup(String key) { 1489 1490 return m_cacheGroup.get(key); 1491 } 1492 1493 /** 1494 * Returns the locale cached with the given cache key or <code>null</code> if not found.<p> 1495 * 1496 * @param key the cache key to look for 1497 * 1498 * @return the locale cached with the given cache key 1499 */ 1500 public Locale getCachedLocale(String key) { 1501 1502 if (m_cacheLocale == null) { 1503 // this may be accessed before initialization 1504 return null; 1505 } 1506 return m_cacheLocale.get(key); 1507 } 1508 1509 /** 1510 * Returns the lock cached with the given root path or <code>null</code> if not found.<p> 1511 * 1512 * @param rootPath the root path to look for 1513 * 1514 * @return the lock cached with the given root path 1515 */ 1516 public CmsLock getCachedLock(String rootPath) { 1517 1518 return m_cacheLock.get(rootPath); 1519 } 1520 1521 /** 1522 * Returns the memory object cached with the given cache key or <code>null</code> if not found.<p> 1523 * 1524 * @param key the cache key to look for 1525 * 1526 * @return the memory object cached with the given cache key 1527 */ 1528 public Object getCachedMemObject(String key) { 1529 1530 return m_cacheMemObject.get(key); 1531 } 1532 1533 /** 1534 * Returns the organizational unit cached with the given cache key or <code>null</code> if not found.<p> 1535 * 1536 * @param key the cache key to look for, this may be the organizational unit's uuid or the fqn 1537 * 1538 * @return the organizational unit cached with the given cache key 1539 */ 1540 public CmsOrganizationalUnit getCachedOrgUnit(String key) { 1541 1542 return m_cacheOrgUnit.get(key); 1543 } 1544 1545 /** 1546 * Returns the permission check result cached with the given cache key or <code>null</code> if not found.<p> 1547 * 1548 * @param key the cache key to look for 1549 * 1550 * @return the permission check result cached with the given cache key 1551 */ 1552 public I_CmsPermissionHandler.CmsPermissionCheckResult getCachedPermission(String key) { 1553 1554 return m_cachePermission.get(key); 1555 } 1556 1557 /** 1558 * Returns the project cached with the given cache key or <code>null</code> if not found.<p> 1559 * 1560 * @param key the cache key to look for, this may be the project's uuid or the fqn 1561 * 1562 * @return the project cached with the given cache key 1563 */ 1564 public CmsProject getCachedProject(String key) { 1565 1566 return m_cacheProject.get(key); 1567 } 1568 1569 /** 1570 * Returns the project resources list cached with the given cache key or <code>null</code> if not found.<p> 1571 * 1572 * @param key the cache key to look for 1573 * 1574 * @return the project resources list cached with the given cache key 1575 */ 1576 public List<CmsResource> getCachedProjectResources(String key) { 1577 1578 return m_cacheProjectResources.get(key); 1579 } 1580 1581 /** 1582 * Returns the property cached with the given cache key or <code>null</code> if not found.<p> 1583 * 1584 * @param key the cache key to look for 1585 * 1586 * @return the property cached with the given cache key 1587 */ 1588 public CmsProperty getCachedProperty(String key) { 1589 1590 return m_cacheProperty.get(key); 1591 } 1592 1593 /** 1594 * Returns the property list cached with the given cache key or <code>null</code> if not found.<p> 1595 * 1596 * @param key the cache key to look for 1597 * 1598 * @return the property list cached with the given cache key 1599 */ 1600 public List<CmsProperty> getCachedPropertyList(String key) { 1601 1602 return m_cachePropertyList.get(key); 1603 } 1604 1605 /** 1606 * Returns the published resources list cached with the given cache key or <code>null</code> if not found.<p> 1607 * 1608 * @param cacheKey the cache key to look for 1609 * 1610 * @return the published resources list cached with the given cache key 1611 */ 1612 public List<CmsPublishedResource> getCachedPublishedResources(String cacheKey) { 1613 1614 return m_cachePublishedResources.get(cacheKey); 1615 } 1616 1617 /** 1618 * Returns the publish job with the given cache key or <code>null</code> if not found.<p> 1619 * 1620 * @param key the cache key to look for 1621 * 1622 * @return the publish job with the given cache key 1623 */ 1624 public CmsPublishJobInfoBean getCachedPublishJob(String key) { 1625 1626 synchronized (m_publishQueue) { 1627 for (Object obj : m_publishQueue) { 1628 CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj; 1629 if (publishJob.getPublishHistoryId().toString().equals(key)) { 1630 return publishJob; 1631 } 1632 } 1633 } 1634 return null; 1635 } 1636 1637 /** 1638 * Returns the publish job from the history with the given cache key or <code>null</code> if not found.<p> 1639 * 1640 * @param key the cache key to look for 1641 * 1642 * @return the publish job with the given cache key 1643 */ 1644 public CmsPublishJobInfoBean getCachedPublishJobInHistory(String key) { 1645 1646 for (Object obj : m_publishHistory) { 1647 CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj; 1648 if (publishJob.getPublishHistoryId().toString().equals(key)) { 1649 return publishJob; 1650 } 1651 } 1652 1653 return null; 1654 } 1655 1656 /** 1657 * Returns the resource cached with the given cache key or <code>null</code> if not found.<p> 1658 * 1659 * @param key the cache key to look for 1660 * 1661 * @return the resource cached with the given cache key 1662 */ 1663 public CmsResource getCachedResource(String key) { 1664 1665 return m_cacheResource.get(key); 1666 } 1667 1668 /** 1669 * Returns the resource list cached with the given cache key or <code>null</code> if not found.<p> 1670 * 1671 * @param key the cache key to look for 1672 * 1673 * @return the resource list cached with the given cache key 1674 */ 1675 public List<CmsResource> getCachedResourceList(String key) { 1676 1677 return m_cacheResourceList.get(key); 1678 } 1679 1680 /** 1681 * Returns the value cached with the given cache key or <code>null</code> if not found.<p> 1682 * 1683 * @param key the cache key to look for 1684 * 1685 * @return if the user has the given role 1686 */ 1687 public Boolean getCachedRole(String key) { 1688 1689 return m_cacheHasRoles.get(key); 1690 } 1691 1692 /** 1693 * Returns the value cached with the given cache key or <code>null</code> if not found.<p> 1694 * 1695 * @param key the cache key to look for 1696 * 1697 * @return list of roles 1698 */ 1699 public List<CmsRole> getCachedRoleList(String key) { 1700 1701 return m_cacheRoleLists.get(key); 1702 } 1703 1704 /** 1705 * Returns the user cached with the given cache key or <code>null</code> if not found.<p> 1706 * 1707 * @param key the cache key to look for, this may be the user's uuid or the fqn 1708 * 1709 * @return the user cached with the given cache key 1710 */ 1711 public CmsUser getCachedUser(String key) { 1712 1713 return m_cacheUser.get(key); 1714 } 1715 1716 /** 1717 * Returns the user groups list cached with the given cache key or <code>null</code> if not found.<p> 1718 * 1719 * @param userId the user id 1720 * @param key the cache key to look for 1721 * 1722 * @return the user groups list cached with the given cache key 1723 */ 1724 public List<CmsGroup> getCachedUserGroups(CmsUUID userId, String key) { 1725 1726 return m_cacheUserGroups.getGroups(userId, key); 1727 } 1728 1729 /** 1730 * Returns the user list cached with the given cache key or <code>null</code> if not found.<p> 1731 * 1732 * @param key the cache key to look for 1733 * 1734 * @return the user groups list cached with the given cache key 1735 */ 1736 public List<CmsUser> getCachedUserList(String key) { 1737 1738 return m_cacheUserList.get(key); 1739 } 1740 1741 /** 1742 * Returns the vfs object cached with the given cache key or <code>null</code> if not found.<p> 1743 * 1744 * @param key the cache key to look for 1745 * 1746 * @return the vfs object cached with the given cache key 1747 */ 1748 public Object getCachedVfsObject(String key) { 1749 1750 return m_cacheVfsObject.get(key); 1751 } 1752 1753 /** 1754 * Returns the xml permanent entity content cached with the given systemId or <code>null</code> if not found.<p> 1755 * 1756 * @param systemId the cache key to look for 1757 * 1758 * @return the xml permanent entity content cached with the given cache key 1759 */ 1760 public byte[] getCachedXmlPermanentEntity(String systemId) { 1761 1762 return m_cacheXmlPermanentEntity.get(systemId); 1763 } 1764 1765 /** 1766 * Returns the xml temporary entity content cached with the given cache key or <code>null</code> if not found.<p> 1767 * 1768 * @param key the cache key to look for 1769 * 1770 * @return the xml temporary entity content cached with the given cache key 1771 */ 1772 public byte[] getCachedXmlTemporaryEntity(String key) { 1773 1774 return m_cacheXmlTemporaryEntity.get(key); 1775 } 1776 1777 /** 1778 * Returns the configuration.<p> 1779 * 1780 * @return the configuration 1781 */ 1782 public CmsMemoryMonitorConfiguration getConfiguration() { 1783 1784 return m_configuration; 1785 } 1786 1787 /** 1788 * Returns the next publish job from the publish job queue.<p> 1789 * 1790 * @return the next publish job 1791 */ 1792 public CmsPublishJobInfoBean getFirstCachedPublishJob() { 1793 1794 synchronized (m_publishQueue) { 1795 if (!m_publishQueue.isEmpty()) { 1796 return (CmsPublishJobInfoBean)m_publishQueue.get(); 1797 } else { 1798 return null; 1799 } 1800 } 1801 } 1802 1803 /** 1804 * Gets the group list cache. 1805 * 1806 * @return the group list cache 1807 */ 1808 public CmsGroupListCache getGroupListCache() { 1809 1810 return m_cacheUserGroups; 1811 } 1812 1813 /** 1814 * Returns the log count.<p> 1815 * 1816 * @return the log count 1817 */ 1818 public int getLogCount() { 1819 1820 return m_logCount; 1821 } 1822 1823 /** 1824 * Returns the current memory status.<p> 1825 * 1826 * @return the memory status 1827 */ 1828 public CmsMemoryStatus getMemoryStatus() { 1829 1830 m_memoryCurrent.update(); 1831 return m_memoryCurrent; 1832 } 1833 1834 /** 1835 * Gets the cache for OU / resource associations. 1836 * 1837 * @return the cache 1838 */ 1839 public LoadingCache<ResourceOUCacheKey, ResourceOUMap> getResourceOuCache() { 1840 1841 return m_resourceOuCache; 1842 } 1843 1844 /** 1845 * Initializes the monitor with the provided configuration.<p> 1846 * 1847 * @param configuration the configuration to use 1848 */ 1849 public void initialize(CmsSystemConfiguration configuration) { 1850 1851 CmsCacheSettings cacheSettings = configuration.getCacheSettings(); 1852 1853 m_memoryAverage = new CmsMemoryStatus(); 1854 m_memoryCurrent = new CmsMemoryStatus(); 1855 1856 m_warningSendSinceLastStatus = false; 1857 m_warningLoggedSinceLastStatus = false; 1858 m_lastEmailWarning = 0; 1859 m_lastEmailStatus = 0; 1860 m_lastLogStatus = 0; 1861 m_lastLogWarning = 0; 1862 m_lastClearCache = 0; 1863 m_configuration = configuration.getCmsMemoryMonitorConfiguration(); 1864 1865 m_intervalWarning = 720 * 60000; 1866 m_maxUsagePercent = 90; 1867 1868 m_intervalEmail = m_configuration.getEmailInterval() * 1000; 1869 m_intervalLog = m_configuration.getLogInterval() * 1000; 1870 1871 if (m_configuration.getWarningInterval() > 0) { 1872 m_intervalWarning = m_configuration.getWarningInterval(); 1873 } 1874 m_intervalWarning *= 1000; 1875 1876 if (m_configuration.getMaxUsagePercent() > 0) { 1877 m_maxUsagePercent = m_configuration.getMaxUsagePercent(); 1878 } 1879 1880 if (CmsLog.INIT.isInfoEnabled()) { 1881 CmsLog.INIT.info( 1882 Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_LOG_1, Integer.valueOf(m_intervalLog / 1000))); 1883 CmsLog.INIT.info( 1884 Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_EMAIL_1, Integer.valueOf(m_intervalEmail / 1000))); 1885 CmsLog.INIT.info( 1886 Messages.get().getBundle().key( 1887 Messages.LOG_MM_INTERVAL_WARNING_1, 1888 Integer.valueOf(m_intervalWarning / 1000))); 1889 CmsLog.INIT.info( 1890 Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_MAX_USAGE_1, Integer.valueOf(m_maxUsagePercent))); 1891 1892 if ((m_configuration.getEmailReceiver() == null) || (m_configuration.getEmailSender() == null)) { 1893 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_DISABLED_0)); 1894 } else { 1895 CmsLog.INIT.info( 1896 Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_SENDER_1, m_configuration.getEmailSender())); 1897 Iterator<String> i = m_configuration.getEmailReceiver().iterator(); 1898 int n = 0; 1899 while (i.hasNext()) { 1900 CmsLog.INIT.info( 1901 Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_RECEIVER_2, Integer.valueOf(n + 1), i.next())); 1902 n++; 1903 } 1904 } 1905 } 1906 1907 // create and register all system caches 1908 1909 // temporary xml entities cache 1910 m_cacheXmlTemporaryEntity = createLRUCacheMap(128); 1911 register(CmsXmlEntityResolver.class.getName() + ".xmlEntityTemporaryCache", m_cacheXmlTemporaryEntity); 1912 1913 // permanent xml entities cache 1914 m_cacheXmlPermanentEntity = new ConcurrentHashMap<String, byte[]>(32); 1915 register(CmsXmlEntityResolver.class.getName() + ".xmlEntityPermanentCache", m_cacheXmlPermanentEntity); 1916 1917 // xml content definitions cache 1918 m_cacheContentDefinitions = createLRUCacheMap(64); 1919 register(CmsXmlEntityResolver.class.getName() + ".contentDefinitionsCache", m_cacheContentDefinitions); 1920 1921 // lock cache 1922 m_cacheLock = new ConcurrentHashMap<String, CmsLock>(); 1923 register(CmsLockManager.class.getName(), m_cacheLock); 1924 1925 // locale cache 1926 m_cacheLocale = new ConcurrentHashMap<String, Locale>(); 1927 register(CmsLocaleManager.class.getName(), m_cacheLocale); 1928 1929 // permissions cache 1930 m_cachePermission = createLRUCacheMap(cacheSettings.getPermissionCacheSize()); 1931 register(CmsSecurityManager.class.getName(), m_cachePermission); 1932 1933 // user cache 1934 m_cacheUser = createLRUCacheMap(cacheSettings.getUserCacheSize()); 1935 register(CmsDriverManager.class.getName() + ".userCache", m_cacheUser); 1936 1937 // user list cache 1938 m_cacheUserList = createLRUCacheMap(cacheSettings.getUserCacheSize()); 1939 register(CmsDriverManager.class.getName() + ".userListCache", m_cacheUserList); 1940 1941 // group cache 1942 m_cacheGroup = createLRUCacheMap(cacheSettings.getGroupCacheSize()); 1943 register(CmsDriverManager.class.getName() + ".groupCache", m_cacheGroup); 1944 1945 // organizational unit cache 1946 m_cacheOrgUnit = createLRUCacheMap(cacheSettings.getOrgUnitCacheSize()); 1947 register(CmsDriverManager.class.getName() + ".orgUnitCache", m_cacheOrgUnit); 1948 1949 // user groups list cache 1950 m_cacheUserGroups = new CmsGroupListCache(cacheSettings.getUserGroupsCacheSize()); 1951 register(CmsDriverManager.class.getName() + ".userGroupsCache", m_cacheUserGroups); 1952 1953 // project cache 1954 m_cacheProject = createLRUCacheMap(cacheSettings.getProjectCacheSize()); 1955 register(CmsDriverManager.class.getName() + ".projectCache", m_cacheProject); 1956 1957 // project resources cache cache 1958 m_cacheProjectResources = createLRUCacheMap(cacheSettings.getProjectResourcesCacheSize()); 1959 register(CmsDriverManager.class.getName() + ".projectResourcesCache", m_cacheProjectResources); 1960 1961 // publish history 1962 int size = configuration.getPublishManager().getPublishHistorySize(); 1963 Buffer buffer = CmsPublishHistory.getQueue(size); 1964 m_publishHistory = SynchronizedBuffer.decorate(buffer); 1965 register(CmsPublishHistory.class.getName() + ".publishHistory", buffer); 1966 1967 // publish queue 1968 buffer = CmsPublishQueue.getQueue(); 1969 m_publishQueue = SynchronizedBuffer.decorate(buffer); 1970 register(CmsPublishQueue.class.getName() + ".publishQueue", buffer); 1971 1972 // resource cache 1973 m_cacheResource = createLRUCacheMap(cacheSettings.getResourceCacheSize()); 1974 register(CmsDriverManager.class.getName() + ".resourceCache", m_cacheResource); 1975 1976 // roles cache 1977 m_cacheHasRoles = createLRUCacheMap(cacheSettings.getRolesCacheSize()); 1978 register(CmsDriverManager.class.getName() + ".rolesCache", m_cacheHasRoles); 1979 1980 // role lists cache 1981 m_cacheRoleLists = createLRUCacheMap(cacheSettings.getRolesCacheSize()); 1982 register(CmsDriverManager.class.getName() + ".roleListsCache", m_cacheRoleLists); 1983 1984 // resource list cache 1985 m_cacheResourceList = createLRUCacheMap(cacheSettings.getResourcelistCacheSize()); 1986 register(CmsDriverManager.class.getName() + ".resourceListCache", m_cacheResourceList); 1987 1988 // property cache 1989 m_cacheProperty = createLRUCacheMap(cacheSettings.getPropertyCacheSize()); 1990 register(CmsDriverManager.class.getName() + ".propertyCache", m_cacheProperty); 1991 1992 // property list cache 1993 m_cachePropertyList = createLRUCacheMap(cacheSettings.getPropertyListsCacheSize()); 1994 register(CmsDriverManager.class.getName() + ".propertyListCache", m_cachePropertyList); 1995 1996 // published resources list cache 1997 m_cachePublishedResources = createLRUCacheMap(5); 1998 register(CmsDriverManager.class.getName() + ".publishedResourcesCache", m_cachePublishedResources); 1999 2000 // acl cache 2001 m_cacheAccessControlList = createLRUCacheMap(cacheSettings.getAclCacheSize()); 2002 register(CmsDriverManager.class.getName() + ".accessControlListCache", m_cacheAccessControlList); 2003 2004 // vfs object cache 2005 m_cacheVfsObject = new ConcurrentHashMap<String, Object>(); 2006 register(CmsVfsMemoryObjectCache.class.getName(), m_cacheVfsObject); 2007 2008 // memory object cache 2009 m_cacheMemObject = new ConcurrentHashMap<String, Object>(); 2010 register(CmsMemoryObjectCache.class.getName(), m_cacheMemObject); 2011 2012 if (LOG.isDebugEnabled()) { 2013 // this will happen only once during system startup 2014 LOG.debug(Messages.get().getBundle().key(Messages.LOG_MM_CREATED_1, new Date(System.currentTimeMillis()))); 2015 } 2016 } 2017 2018 /** 2019 * Checks if the property cache is enabled.<p> 2020 * 2021 * @return <code>true</code> if the property cache is enabled 2022 * 2023 * @deprecated use {@link #isEnabled(CacheType)} instead 2024 */ 2025 @Deprecated 2026 public boolean isCacheProperty() { 2027 2028 return isEnabled(CacheType.PROPERTY); 2029 } 2030 2031 /** 2032 * Checks if the property list cache is enabled.<p> 2033 * 2034 * @return <code>true</code> if the property list cache is enabled 2035 * 2036 * @deprecated use {@link #isEnabled(CacheType)} instead 2037 */ 2038 @Deprecated 2039 public boolean isCachePropertyList() { 2040 2041 return isEnabled(CacheType.PROPERTY_LIST); 2042 } 2043 2044 /** 2045 * Checks if the resource cache is enabled.<p> 2046 * 2047 * @return <code>true</code> if the resource cache is enabled 2048 * 2049 * @deprecated use {@link #isEnabled(CacheType)} instead 2050 */ 2051 @Deprecated 2052 public boolean isCacheResource() { 2053 2054 return isEnabled(CacheType.RESOURCE); 2055 } 2056 2057 /** 2058 * Checks if the resource list cache is enabled.<p> 2059 * 2060 * @return <code>true</code> if the resource list cache is enabled 2061 * 2062 * @deprecated use {@link #isEnabled(CacheType)} instead 2063 */ 2064 @Deprecated 2065 public boolean isCacheResourceList() { 2066 2067 return isEnabled(CacheType.RESOURCE_LIST); 2068 } 2069 2070 /** 2071 * Checks if the given cache is enabled.<p> 2072 * 2073 * @param type the cache type to check 2074 * 2075 * @return <code>true</code> if the given cache is enabled 2076 */ 2077 public boolean isEnabled(CacheType type) { 2078 2079 return (m_disabled.get(type) == null); 2080 } 2081 2082 /** 2083 * Checks if there is a registered monitored object with the given key.<p> 2084 * 2085 * @param key the key to look for 2086 * 2087 * @return <code>true</code> if there is a registered monitored object with the given key 2088 */ 2089 public boolean isMonitoring(String key) { 2090 2091 return (m_monitoredObjects.get(key) != null); 2092 } 2093 2094 /** 2095 * @see org.opencms.scheduler.I_CmsScheduledJob#launch(CmsObject, Map) 2096 */ 2097 public String launch(CmsObject cms, Map<String, String> parameters) throws Exception { 2098 2099 CmsMemoryMonitor monitor = OpenCms.getMemoryMonitor(); 2100 2101 // make sure job is not launched twice 2102 if (m_currentlyRunning) { 2103 return null; 2104 } 2105 2106 try { 2107 m_currentlyRunning = true; 2108 2109 // update the memory status 2110 monitor.updateStatus(); 2111 2112 // check if the system is in a low memory condition 2113 if (monitor.lowMemory()) { 2114 // log warning 2115 monitor.monitorWriteLog(true); 2116 // send warning email 2117 monitor.monitorSendEmail(true); 2118 // clean up caches 2119 monitor.clearCaches(); 2120 } 2121 2122 // check if regular a log entry must be written 2123 if ((System.currentTimeMillis() - monitor.m_lastLogStatus) > monitor.m_intervalLog) { 2124 monitor.monitorWriteLog(false); 2125 } 2126 2127 // check if the memory status email must be send 2128 if ((System.currentTimeMillis() - monitor.m_lastEmailStatus) > monitor.m_intervalEmail) { 2129 monitor.monitorSendEmail(false); 2130 } 2131 } finally { 2132 // make sure state is reset even if an error occurs, 2133 // otherwise MM will not be executed after an error 2134 m_currentlyRunning = false; 2135 } 2136 2137 return null; 2138 } 2139 2140 /** 2141 * Returns true if the system runs low on memory.<p> 2142 * 2143 * @return true if the system runs low on memory 2144 */ 2145 public boolean lowMemory() { 2146 2147 return ((m_maxUsagePercent > 0) && (m_memoryCurrent.getUsage() > m_maxUsagePercent)); 2148 } 2149 2150 /** 2151 * Adds a new object to the monitor.<p> 2152 * 2153 * @param objectName name of the object 2154 * @param object the object for monitoring 2155 */ 2156 public void register(String objectName, Object object) { 2157 2158 if (enabled()) { 2159 m_monitoredObjects.put(objectName, object); 2160 } 2161 } 2162 2163 /** 2164 * Checks if some kind of persistence is required.<p> 2165 * 2166 * This could be overwritten in a distributed environment.<p> 2167 * 2168 * @return <code>true</code> if some kind of persistence is required 2169 */ 2170 public boolean requiresPersistency() { 2171 2172 return true; 2173 } 2174 2175 /** 2176 * Sets if the property cache is enabled.<p> 2177 * 2178 * @param cacheProperty if the property cache is enabled 2179 * 2180 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2181 */ 2182 @Deprecated 2183 public void setCacheProperty(boolean cacheProperty) { 2184 2185 if (cacheProperty) { 2186 enableCache(CacheType.PROPERTY); 2187 } else { 2188 disableCache(CacheType.PROPERTY); 2189 } 2190 } 2191 2192 /** 2193 * Sets if the property list cache is enabled.<p> 2194 * 2195 * @param cachePropertyList if the property list cache is enabled 2196 * 2197 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2198 */ 2199 @Deprecated 2200 public void setCachePropertyList(boolean cachePropertyList) { 2201 2202 if (cachePropertyList) { 2203 enableCache(CacheType.PROPERTY_LIST); 2204 } else { 2205 disableCache(CacheType.PROPERTY_LIST); 2206 } 2207 } 2208 2209 /** 2210 * Sets if the resource cache is enabled.<p> 2211 * 2212 * @param cacheResource if the resource cache is enabled 2213 * 2214 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2215 */ 2216 @Deprecated 2217 public void setCacheResource(boolean cacheResource) { 2218 2219 if (cacheResource) { 2220 enableCache(CacheType.RESOURCE); 2221 } else { 2222 disableCache(CacheType.RESOURCE); 2223 } 2224 } 2225 2226 /** 2227 * Sets if the resource list cache is enabled.<p> 2228 * 2229 * @param cacheResourceList if the resource list cache is enabled 2230 * 2231 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2232 */ 2233 @Deprecated 2234 public void setCacheResourceList(boolean cacheResourceList) { 2235 2236 if (cacheResourceList) { 2237 enableCache(CacheType.RESOURCE_LIST); 2238 } else { 2239 disableCache(CacheType.RESOURCE_LIST); 2240 } 2241 } 2242 2243 /** 2244 * Flushes all cached objects.<p> 2245 * 2246 * @throws Exception if something goes wrong 2247 */ 2248 public void shutdown() throws Exception { 2249 2250 for (CacheType type : CacheType.values()) { 2251 flushCache(type); 2252 } 2253 } 2254 2255 /** 2256 * Removes the given xml content definition from the cache.<p> 2257 * 2258 * @param key the cache key to remove from cache 2259 */ 2260 public void uncacheContentDefinition(String key) { 2261 2262 m_cacheContentDefinitions.remove(key); 2263 } 2264 2265 /** 2266 * Removes the given group from the cache.<p> 2267 * 2268 * The group is removed by name AND also by uuid.<p> 2269 * 2270 * @param group the group to remove from cache 2271 */ 2272 public void uncacheGroup(CmsGroup group) { 2273 2274 m_cacheGroup.remove(group.getId().toString()); 2275 m_cacheGroup.remove(group.getName()); 2276 } 2277 2278 /** 2279 * Removes the cached lock for the given root path from the cache.<p> 2280 * 2281 * @param rootPath the root path of the lock to remove from cache 2282 */ 2283 public void uncacheLock(String rootPath) { 2284 2285 m_cacheLock.remove(rootPath); 2286 } 2287 2288 /** 2289 * Removes the given organizational unit from the cache.<p> 2290 * 2291 * The organizational unit is removed by name AND also by uuid.<p> 2292 * 2293 * @param orgUnit the organizational unit to remove from cache 2294 */ 2295 public void uncacheOrgUnit(CmsOrganizationalUnit orgUnit) { 2296 2297 m_cacheOrgUnit.remove(orgUnit.getId().toString()); 2298 m_cacheOrgUnit.remove(orgUnit.getName()); 2299 } 2300 2301 /** 2302 * Removes the given project from the cache.<p> 2303 * 2304 * The project is removed by name AND also by uuid.<p> 2305 * 2306 * @param project the project to remove from cache 2307 */ 2308 public void uncacheProject(CmsProject project) { 2309 2310 m_cacheProject.remove(project.getUuid().toString()); 2311 m_cacheProject.remove(project.getName()); 2312 } 2313 2314 /** 2315 * Removes the given publish job from the cache.<p> 2316 * 2317 * @param publishJob the publish job to remove 2318 */ 2319 public void uncachePublishJob(CmsPublishJobInfoBean publishJob) { 2320 2321 m_publishQueue.remove(publishJob); 2322 } 2323 2324 /** 2325 * Removes the given publish job from the history.<p> 2326 * 2327 * @param publishJob the publish job to remove 2328 */ 2329 public void uncachePublishJobInHistory(CmsPublishJobInfoBean publishJob) { 2330 2331 m_publishHistory.remove(publishJob); 2332 } 2333 2334 /** 2335 * Removes the given user from the cache.<p> 2336 * 2337 * The user is removed by name AND also by uuid.<p> 2338 * 2339 * @param user the user to remove from cache 2340 */ 2341 public void uncacheUser(CmsUser user) { 2342 2343 m_cacheUser.remove(user.getId().toString()); 2344 m_cacheUser.remove(user.getName()); 2345 } 2346 2347 /** 2348 * Removes the given vfs object from the cache.<p> 2349 * 2350 * @param key the cache key to remove from cache 2351 */ 2352 public void uncacheVfsObject(String key) { 2353 2354 m_cacheVfsObject.remove(key); 2355 } 2356 2357 /** 2358 * Removes the given xml temporary entity from the cache.<p> 2359 * 2360 * @param key the cache key to remove from cache 2361 */ 2362 public void uncacheXmlTemporaryEntity(String key) { 2363 2364 m_cacheXmlTemporaryEntity.remove(key); 2365 } 2366 2367 /** 2368 * Clears the OpenCms caches.<p> 2369 */ 2370 protected void clearCaches() { 2371 2372 if ((m_lastClearCache + INTERVAL_CLEAR) > System.currentTimeMillis()) { 2373 // if the cache has already been cleared less then 15 minutes ago we skip this because 2374 // clearing the caches to often will hurt system performance and the 2375 // setup seems to be in trouble anyway 2376 return; 2377 } 2378 m_lastClearCache = System.currentTimeMillis(); 2379 if (LOG.isWarnEnabled()) { 2380 LOG.warn(Messages.get().getBundle().key(Messages.LOG_CLEAR_CACHE_MEM_CONS_0)); 2381 } 2382 OpenCms.fireCmsEvent( 2383 new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap())); 2384 System.gc(); 2385 } 2386 2387 /** 2388 * Returns the cache costs of a monitored object.<p> 2389 * 2390 * <code>obj</code> must be of type {@link CmsLruCache}.<p> 2391 * 2392 * @param obj the object 2393 * 2394 * @return the cache costs or "-" 2395 */ 2396 protected long getCosts(Object obj) { 2397 2398 long costs = 0; 2399 if (obj instanceof CmsLruCache) { 2400 costs = ((CmsLruCache)obj).getObjectCosts(); 2401 if (costs < 0) { 2402 costs = 0; 2403 } 2404 } 2405 2406 return costs; 2407 } 2408 2409 /** 2410 * Returns the number of items within a monitored object.<p> 2411 * 2412 * <code>obj</code> must be of type {@link CmsLruCache} or {@link Map}.<p> 2413 * 2414 * @param obj the object 2415 * 2416 * @return the number of items or "-" 2417 */ 2418 protected String getItems(Object obj) { 2419 2420 if (obj instanceof CmsLruCache) { 2421 return Integer.toString(((CmsLruCache)obj).size()); 2422 } 2423 if (obj instanceof Map) { 2424 return Integer.toString(((Map<?, ?>)obj).size()); 2425 } 2426 if (obj instanceof CmsGroupListCache) { 2427 return "" + ((CmsGroupListCache)obj).size(); 2428 } 2429 return "-"; 2430 } 2431 2432 /** 2433 * Returns the total size of key strings within a monitored map.<p> 2434 * 2435 * The keys must be of type {@link String}.<p> 2436 * 2437 * @param map the map 2438 * @param depth the max recursion depth for calculation the size 2439 * 2440 * @return total size of key strings 2441 */ 2442 protected long getKeySize(Map<?, ?> map, int depth) { 2443 2444 long keySize = 0; 2445 try { 2446 Object[] values = map.values().toArray(); 2447 for (int i = 0, s = values.length; i < s; i++) { 2448 2449 Object obj = values[i]; 2450 2451 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 2452 keySize += getKeySize((Map<?, ?>)obj, depth + 1); 2453 continue; 2454 } 2455 } 2456 values = null; 2457 2458 Object[] keys = map.keySet().toArray(); 2459 for (int i = 0, s = keys.length; i < s; i++) { 2460 2461 Object obj = keys[i]; 2462 2463 if (obj instanceof String) { 2464 String st = (String)obj; 2465 keySize += (st.length() * 2); 2466 } 2467 } 2468 } catch (ConcurrentModificationException e) { 2469 // this might happen since even the .toArray() method internally creates an iterator 2470 } catch (Throwable t) { 2471 // catch all other exceptions otherwise the whole monitor will stop working 2472 if (LOG.isDebugEnabled()) { 2473 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 2474 } 2475 } 2476 2477 return keySize; 2478 } 2479 2480 /** 2481 * Returns the total size of key strings within a monitored object.<p> 2482 * 2483 * <code>obj</code> must be of type {@link Map}, the keys must be of type {@link String}.<p> 2484 * 2485 * @param obj the object 2486 * 2487 * @return the total size of key strings 2488 */ 2489 protected long getKeySize(Object obj) { 2490 2491 if (obj instanceof Map) { 2492 return getKeySize((Map<?, ?>)obj, 1); 2493 } 2494 2495 return 0; 2496 } 2497 2498 /** 2499 * Returns the max costs for all items within a monitored object.<p> 2500 * 2501 * <code>obj</code> must be of type {@link CmsLruCache} or {@link LRUMap}.<p> 2502 * 2503 * @param obj the object 2504 * 2505 * @return max cost limit or "-" 2506 */ 2507 protected String getLimit(Object obj) { 2508 2509 if (obj instanceof CmsLruCache) { 2510 return Long.toString(((CmsLruCache)obj).getMaxCacheCosts()); 2511 } 2512 if (obj instanceof LRUMap) { 2513 return Integer.toString(((LRUMap)obj).maxSize()); 2514 } 2515 2516 return "-"; 2517 } 2518 2519 /** 2520 * Sends a warning or status email with OpenCms Memory information.<p> 2521 * 2522 * @param warning if true, send a memory warning email 2523 */ 2524 protected void monitorSendEmail(boolean warning) { 2525 2526 if ((m_configuration.getEmailSender() == null) || (m_configuration.getEmailReceiver() == null)) { 2527 // send no mails if not fully configured 2528 return; 2529 } else if (warning 2530 && (m_warningSendSinceLastStatus 2531 && !((m_intervalEmail <= 0) 2532 && (System.currentTimeMillis() < (m_lastEmailWarning + m_intervalWarning))))) { 2533 // send no warning email if no status email has been send since the last warning 2534 // if status is disabled, send no warn email if warn interval has not passed 2535 return; 2536 } else if ((!warning) && (m_intervalEmail <= 0)) { 2537 // if email iterval is <= 0 status email is disabled 2538 return; 2539 } 2540 String date = CmsDateUtil.getDateTimeShort(System.currentTimeMillis()); 2541 String subject; 2542 String content = ""; 2543 if (warning) { 2544 m_warningSendSinceLastStatus = true; 2545 m_lastEmailWarning = System.currentTimeMillis(); 2546 subject = "OpenCms Memory W A R N I N G [" 2547 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2548 + "/" 2549 + date 2550 + "]"; 2551 content += "W A R N I N G !\nOpenCms memory consumption on server " 2552 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2553 + " has reached a critical level !\n\n" 2554 + "The configured limit is " 2555 + m_maxUsagePercent 2556 + "%\n\n"; 2557 } else { 2558 m_warningSendSinceLastStatus = false; 2559 m_lastEmailStatus = System.currentTimeMillis(); 2560 subject = "OpenCms Memory Status [" 2561 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2562 + "/" 2563 + date 2564 + "]"; 2565 } 2566 2567 content += "Memory usage report of OpenCms server " 2568 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2569 + " at " 2570 + date 2571 + "\n\n" 2572 + "Memory maximum heap size: " 2573 + m_memoryCurrent.getMaxMemory() 2574 + " mb\n" 2575 + "Memory current heap size: " 2576 + m_memoryCurrent.getTotalMemory() 2577 + " mb\n\n" 2578 + "Memory currently used : " 2579 + m_memoryCurrent.getUsedMemory() 2580 + " mb (" 2581 + m_memoryCurrent.getUsage() 2582 + "%)\n" 2583 + "Memory currently unused : " 2584 + m_memoryCurrent.getFreeMemory() 2585 + " mb\n\n\n"; 2586 2587 if (warning) { 2588 content += "*** Please take action NOW to ensure that no OutOfMemoryException occurs.\n\n\n"; 2589 } 2590 2591 CmsSessionManager sm = OpenCms.getSessionManager(); 2592 2593 if (sm != null) { 2594 content += "Current status of the sessions:\n\n"; 2595 content += "Logged in users : " + sm.getSessionCountAuthenticated() + "\n"; 2596 content += "Currently active sessions: " + sm.getSessionCountCurrent() + "\n"; 2597 content += "Total created sessions : " + sm.getSessionCountTotal() + "\n\n\n"; 2598 } 2599 2600 sm = null; 2601 2602 content += "Current status of the caches:\n\n"; 2603 List<String> keyList = new ArrayList<String>(m_monitoredObjects.keySet()); 2604 Collections.sort(keyList); 2605 long totalSize = 0; 2606 for (Iterator<String> keys = keyList.iterator(); keys.hasNext();) { 2607 String key = keys.next(); 2608 String[] shortKeys = key.split("\\."); 2609 String shortKey = shortKeys[shortKeys.length - 2] + '.' + shortKeys[shortKeys.length - 1]; 2610 PrintfFormat form = new PrintfFormat("%9s"); 2611 Object obj = m_monitoredObjects.get(key); 2612 2613 long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj); 2614 totalSize += size; 2615 2616 content += new PrintfFormat("%-42.42s").sprintf(shortKey) 2617 + " " 2618 + "Entries: " 2619 + form.sprintf(getItems(obj)) 2620 + " " 2621 + "Limit: " 2622 + form.sprintf(getLimit(obj)) 2623 + " " 2624 + "Size: " 2625 + form.sprintf(Long.toString(size)) 2626 + "\n"; 2627 } 2628 content += "\nTotal size of cache memory monitored: " + totalSize + " (" + (totalSize / 1048576) + ")\n\n"; 2629 2630 String from = m_configuration.getEmailSender(); 2631 List<InternetAddress> receivers = new ArrayList<InternetAddress>(); 2632 List<String> receiverEmails = m_configuration.getEmailReceiver(); 2633 try { 2634 if ((from != null) && (receiverEmails != null) && !receiverEmails.isEmpty()) { 2635 Iterator<String> i = receiverEmails.iterator(); 2636 while (i.hasNext()) { 2637 receivers.add(new InternetAddress(i.next())); 2638 } 2639 CmsSimpleMail email = new CmsSimpleMail(); 2640 email.setFrom(from); 2641 email.setTo(receivers); 2642 email.setSubject(subject); 2643 email.setMsg(content); 2644 new CmsMailTransport(email).send(); 2645 } 2646 if (LOG.isInfoEnabled()) { 2647 if (warning) { 2648 LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_WARNING_EMAIL_SENT_0)); 2649 } else { 2650 LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_STATUS_EMAIL_SENT_0)); 2651 } 2652 } 2653 } catch (Exception e) { 2654 e.printStackTrace(); 2655 } 2656 } 2657 2658 /** 2659 * Write a warning or status log entry with OpenCms Memory information.<p> 2660 * 2661 * @param warning if true, write a memory warning log entry 2662 */ 2663 protected void monitorWriteLog(boolean warning) { 2664 2665 if (!LOG.isWarnEnabled()) { 2666 // we need at last warn level for this output 2667 return; 2668 } else if ((!warning) && (!LOG.isInfoEnabled())) { 2669 // if not warning we need info level 2670 return; 2671 } else if (warning 2672 && (m_warningLoggedSinceLastStatus 2673 && !(((m_intervalLog <= 0) 2674 && (System.currentTimeMillis() < (m_lastLogWarning + m_intervalWarning)))))) { 2675 // write no warning log if no status log has been written since the last warning 2676 // if status is disabled, log no warn entry if warn interval has not passed 2677 return; 2678 } else if ((!warning) && (m_intervalLog <= 0)) { 2679 // if log interval is <= 0 status log is disabled 2680 return; 2681 } 2682 2683 if (warning) { 2684 m_lastLogWarning = System.currentTimeMillis(); 2685 m_warningLoggedSinceLastStatus = true; 2686 LOG.warn( 2687 Messages.get().getBundle().key( 2688 Messages.LOG_MM_WARNING_MEM_CONSUME_2, 2689 Long.valueOf(m_memoryCurrent.getUsage()), 2690 Integer.valueOf(m_maxUsagePercent))); 2691 } else { 2692 m_warningLoggedSinceLastStatus = false; 2693 m_lastLogStatus = System.currentTimeMillis(); 2694 } 2695 2696 if (warning) { 2697 LOG.warn( 2698 Messages.get().getBundle().key( 2699 Messages.LOG_MM_WARNING_MEM_STATUS_6, 2700 new Object[] { 2701 Long.valueOf(m_memoryCurrent.getMaxMemory()), 2702 Long.valueOf(m_memoryCurrent.getTotalMemory()), 2703 Long.valueOf(m_memoryCurrent.getFreeMemory()), 2704 Long.valueOf(m_memoryCurrent.getUsedMemory()), 2705 Long.valueOf(m_memoryCurrent.getUsage()), 2706 Integer.valueOf(m_maxUsagePercent)})); 2707 } else { 2708 m_logCount++; 2709 LOG.info( 2710 Messages.get().getBundle().key( 2711 Messages.LOG_MM_LOG_INFO_2, 2712 OpenCms.getSystemInfo().getServerName().toUpperCase(), 2713 String.valueOf(m_logCount))); 2714 2715 List<String> keyList = new ArrayList<String>(m_monitoredObjects.keySet()); 2716 Collections.sort(keyList); 2717 long totalSize = 0; 2718 for (Iterator<String> keys = keyList.iterator(); keys.hasNext();) { 2719 String key = keys.next(); 2720 Object obj = m_monitoredObjects.get(key); 2721 2722 long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj); 2723 totalSize += size; 2724 2725 PrintfFormat name1 = new PrintfFormat("%-80s"); 2726 PrintfFormat name2 = new PrintfFormat("%-50s"); 2727 PrintfFormat form = new PrintfFormat("%9s"); 2728 LOG.info( 2729 Messages.get().getBundle().key( 2730 Messages.LOG_MM_NOWARN_STATUS_5, 2731 new Object[] { 2732 name1.sprintf(key), 2733 name2.sprintf(obj.getClass().getName()), 2734 form.sprintf(getItems(obj)), 2735 form.sprintf(getLimit(obj)), 2736 form.sprintf(Long.toString(size))})); 2737 } 2738 2739 LOG.info( 2740 Messages.get().getBundle().key( 2741 Messages.LOG_MM_WARNING_MEM_STATUS_6, 2742 new Object[] { 2743 Long.valueOf(m_memoryCurrent.getMaxMemory()), 2744 Long.valueOf(m_memoryCurrent.getTotalMemory()), 2745 Long.valueOf(m_memoryCurrent.getFreeMemory()), 2746 Long.valueOf(m_memoryCurrent.getUsedMemory()), 2747 Long.valueOf(m_memoryCurrent.getUsage()), 2748 Integer.valueOf(m_maxUsagePercent), 2749 Long.valueOf(totalSize), 2750 Long.valueOf(totalSize / 1048576)}) 2751 2752 ); 2753 LOG.info( 2754 Messages.get().getBundle().key( 2755 Messages.LOG_MM_WARNING_MEM_STATUS_AVG_6, 2756 new Object[] { 2757 Long.valueOf(m_memoryAverage.getMaxMemory()), 2758 Long.valueOf(m_memoryAverage.getTotalMemory()), 2759 Long.valueOf(m_memoryAverage.getFreeMemory()), 2760 Long.valueOf(m_memoryAverage.getUsedMemory()), 2761 Long.valueOf(m_memoryAverage.getUsage()), 2762 Integer.valueOf(m_memoryAverage.getCount())})); 2763 2764 CmsSessionManager sm = OpenCms.getSessionManager(); 2765 2766 if (sm != null) { 2767 LOG.info( 2768 Messages.get().getBundle().key( 2769 Messages.LOG_MM_SESSION_STAT_3, 2770 String.valueOf(sm.getSessionCountAuthenticated()), 2771 String.valueOf(sm.getSessionCountCurrent()), 2772 String.valueOf(sm.getSessionCountTotal()))); 2773 } 2774 sm = null; 2775 2776 for (Iterator<String> i = OpenCms.getSqlManager().getDbPoolUrls().iterator(); i.hasNext();) { 2777 String poolname = i.next(); 2778 try { 2779 LOG.info( 2780 Messages.get().getBundle().key( 2781 Messages.LOG_MM_CONNECTIONS_3, 2782 poolname, 2783 Integer.toString(OpenCms.getSqlManager().getActiveConnections(poolname)), 2784 Integer.toString(OpenCms.getSqlManager().getIdleConnections(poolname)))); 2785 } catch (Exception exc) { 2786 LOG.info( 2787 Messages.get().getBundle().key( 2788 Messages.LOG_MM_CONNECTIONS_3, 2789 poolname, 2790 Integer.toString(-1), 2791 Integer.toString(-1))); 2792 } 2793 } 2794 2795 LOG.info( 2796 Messages.get().getBundle().key( 2797 Messages.LOG_MM_STARTUP_TIME_2, 2798 CmsDateUtil.getDateTimeShort(OpenCms.getSystemInfo().getStartupTime()), 2799 CmsStringUtil.formatRuntime(OpenCms.getSystemInfo().getRuntime()))); 2800 } 2801 } 2802 2803 /** 2804 * Updates the memory information of the memory monitor.<p> 2805 */ 2806 protected void updateStatus() { 2807 2808 m_memoryCurrent.update(); 2809 m_memoryAverage.calculateAverage(m_memoryCurrent); 2810 } 2811}